Merge master into producer-emails.

This commit is contained in:
Paul Mackay
2015-03-04 19:09:43 +00:00
468 changed files with 11434 additions and 3239 deletions

View File

@@ -3,36 +3,39 @@ require 'spec_helper'
module Admin
describe EnterprisesController do
include AuthenticationWorkflow
let(:distributor_owner) do
user = create(:user)
user.spree_roles = []
user
end
let(:distributor) { create(:distributor_enterprise, owner: distributor_owner ) }
let(:user) do
let(:user) { create_enterprise_user }
let(:distributor_manager) do
user = create(:user)
user.spree_roles = []
distributor.enterprise_roles.build(user: user).save
user
end
let(:distributor_owner) do
user = create(:user)
user.spree_roles = []
user
end
let(:admin_user) do
user = create(:user)
user.spree_roles << Spree::Role.find_or_create_by_name!('admin')
user
end
let(:distributor) { create(:distributor_enterprise, owner: distributor_owner ) }
describe "creating an enterprise" do
let(:country) { Spree::Country.find_by_name 'Australia' }
let(:state) { Spree::State.find_by_name 'Victoria' }
let(:enterprise_params) { {enterprise: {name: 'zzz', email: "bob@example.com", address_attributes: {address1: 'a', city: 'a', zipcode: 'a', country_id: country.id, state_id: state.id}}} }
let(:enterprise_params) { {enterprise: {name: 'zzz', permalink: 'zzz', email: "bob@example.com", address_attributes: {address1: 'a', city: 'a', zipcode: 'a', country_id: country.id, state_id: state.id}}} }
it "grants management permission if the current user is an enterprise user" do
controller.stub spree_current_user: user
enterprise_params[:enterprise][:owner_id] = user
controller.stub spree_current_user: distributor_manager
enterprise_params[:enterprise][:owner_id] = distributor_manager
spree_put :create, enterprise_params
enterprise = Enterprise.find_by_name 'zzz'
user.enterprise_roles.where(enterprise_id: enterprise).first.should be
distributor_manager.enterprise_roles.where(enterprise_id: enterprise).first.should be
end
it "does not grant management permission to admins" do
@@ -45,41 +48,12 @@ module Admin
end
it "it overrides the owner_id submitted by the user unless current_user is super admin" do
controller.stub spree_current_user: user
enterprise_params[:enterprise][:owner_id] = admin_user
controller.stub spree_current_user: distributor_manager
enterprise_params[:enterprise][:owner_id] = user
spree_put :create, enterprise_params
enterprise = Enterprise.find_by_name 'zzz'
user.enterprise_roles.where(enterprise_id: enterprise).first.should be
end
end
describe "updating an enterprise" do
it "allows current owner to change ownership" do
controller.stub spree_current_user: distributor_owner
update_params = { id: distributor, enterprise: { owner_id: user } }
spree_post :update, update_params
distributor.reload
expect(distributor.owner).to eq user
end
it "allows super admin to change ownership" do
controller.stub spree_current_user: admin_user
update_params = { id: distributor, enterprise: { owner_id: user } }
spree_post :update, update_params
distributor.reload
expect(distributor.owner).to eq user
end
it "does not allow managers to change ownership" do
controller.stub spree_current_user: user
update_params = { id: distributor, enterprise: { owner_id: user } }
spree_post :update, update_params
distributor.reload
expect(distributor.owner).to eq distributor_owner
distributor_manager.enterprise_roles.where(enterprise_id: enterprise).first.should be
end
end
@@ -88,25 +62,195 @@ module Admin
context "as manager" do
it "does not allow 'sells' to be changed" do
profile_enterprise.enterprise_roles.build(user: user).save
controller.stub spree_current_user: user
enterprise_params = { id: profile_enterprise.id, enterprise: { sells: 'any' } }
profile_enterprise.enterprise_roles.build(user: distributor_manager).save
controller.stub spree_current_user: distributor_manager
enterprise_params = { id: profile_enterprise, enterprise: { sells: 'any' } }
spree_put :update, enterprise_params
profile_enterprise.reload
expect(profile_enterprise.sells).to eq 'none'
end
it "does not allow owner to be changed" do
controller.stub spree_current_user: distributor_manager
update_params = { id: distributor, enterprise: { owner_id: distributor_manager } }
spree_post :update, update_params
distributor.reload
expect(distributor.owner).to eq distributor_owner
end
it "does not allow managers to be changed" do
controller.stub spree_current_user: distributor_manager
update_params = { id: distributor, enterprise: { user_ids: [distributor_owner.id,distributor_manager.id,user.id] } }
spree_post :update, update_params
distributor.reload
expect(distributor.users).to_not include user
end
end
context "as owner" do
it "allows owner to be changed" do
controller.stub spree_current_user: distributor_owner
update_params = { id: distributor, enterprise: { owner_id: distributor_manager } }
spree_post :update, update_params
distributor.reload
expect(distributor.owner).to eq distributor_manager
end
it "allows managers to be changed" do
controller.stub spree_current_user: distributor_owner
update_params = { id: distributor, enterprise: { user_ids: [distributor_owner.id,distributor_manager.id,user.id] } }
spree_post :update, update_params
distributor.reload
expect(distributor.users).to include user
end
end
context "as super admin" do
it "allows 'sells' to be changed" do
controller.stub spree_current_user: admin_user
enterprise_params = { id: profile_enterprise.id, enterprise: { sells: 'any' } }
enterprise_params = { id: profile_enterprise, enterprise: { sells: 'any' } }
spree_put :update, enterprise_params
profile_enterprise.reload
expect(profile_enterprise.sells).to eq 'any'
end
it "allows owner to be changed" do
controller.stub spree_current_user: admin_user
update_params = { id: distributor, enterprise: { owner_id: distributor_manager } }
spree_post :update, update_params
distributor.reload
expect(distributor.owner).to eq distributor_manager
end
it "allows managers to be changed" do
controller.stub spree_current_user: admin_user
update_params = { id: distributor, enterprise: { user_ids: [distributor_owner.id,distributor_manager.id,user.id] } }
spree_post :update, update_params
distributor.reload
expect(distributor.users).to include user
end
end
end
describe "set_sells" do
let(:enterprise) { create(:enterprise, sells: 'none') }
before do
controller.stub spree_current_user: distributor_manager
end
context "as a normal user" do
it "does not allow 'sells' to be set" do
spree_post :set_sells, { id: enterprise.id, sells: 'none' }
expect(response).to redirect_to spree.unauthorized_path
end
end
context "as a manager" do
before do
enterprise.enterprise_roles.build(user: distributor_manager).save
end
context "allows setting 'sells' to 'none'" do
it "is allowed" do
spree_post :set_sells, { id: enterprise, sells: 'none' }
expect(response).to redirect_to spree.admin_path
expect(flash[:success]).to eq "Congratulations! Registration for #{enterprise.name} is complete!"
expect(enterprise.reload.sells).to eq 'none'
end
context "setting producer_profile_only to true" do
it "is allowed" do
spree_post :set_sells, { id: enterprise, sells: 'none', producer_profile_only: true }
expect(response).to redirect_to spree.admin_path
expect(enterprise.reload.producer_profile_only).to eq true
end
end
end
context "setting 'sells' to 'own'" do
before do
enterprise.sells = 'own'
enterprise.save!
end
context "if the trial has finished" do
before do
enterprise.shop_trial_start_date = (Date.today - 30.days).to_time
enterprise.save!
end
it "is disallowed" do
spree_post :set_sells, { id: enterprise, sells: 'own' }
expect(response).to redirect_to spree.admin_path
trial_expiry = Date.today.strftime("%Y-%m-%d")
expect(flash[:error]).to eq "Sorry, but you've already had a trial. Expired on: #{trial_expiry}"
expect(enterprise.reload.sells).to eq 'own'
expect(enterprise.reload.shop_trial_start_date).to eq (Date.today - 30.days).to_time
end
end
context "if the trial has not finished" do
before do
enterprise.shop_trial_start_date = Date.today.to_time
enterprise.save!
end
it "is allowed, but trial start date is not reset" do
spree_post :set_sells, { id: enterprise, sells: 'own' }
expect(response).to redirect_to spree.admin_path
trial_expiry = (Date.today + 30.days).strftime("%Y-%m-%d")
expect(flash[:notice]).to eq "Welcome back! Your trial expires on: #{trial_expiry}"
expect(enterprise.reload.sells).to eq 'own'
expect(enterprise.reload.shop_trial_start_date).to eq Date.today.to_time
end
end
context "if a trial has not started" do
it "is allowed" do
spree_post :set_sells, { id: enterprise, sells: 'own' }
expect(response).to redirect_to spree.admin_path
expect(flash[:success]).to eq "Congratulations! Registration for #{enterprise.name} is complete!"
expect(enterprise.reload.sells).to eq 'own'
expect(enterprise.reload.shop_trial_start_date).to be > Time.now-(1.minute)
end
end
context "setting producer_profile_only to true" do
it "is ignored" do
spree_post :set_sells, { id: enterprise, sells: 'own', producer_profile_only: true }
expect(response).to redirect_to spree.admin_path
expect(enterprise.reload.producer_profile_only).to be false
end
end
end
context "setting 'sells' to any" do
it "is not allowed" do
spree_post :set_sells, { id: enterprise, sells: 'any' }
expect(response).to redirect_to spree.admin_path
expect(flash[:error]).to eq "Unauthorised"
expect(enterprise.reload.sells).to eq 'none'
end
end
context "settiing 'sells' to 'unspecified'" do
it "is not allowed" do
spree_post :set_sells, { id: enterprise, sells: 'unspecified' }
expect(response).to redirect_to spree.admin_path
expect(flash[:error]).to eq "Unauthorised"
expect(enterprise.reload.sells).to eq 'none'
end
end
end
end
@@ -141,6 +285,15 @@ module Admin
expect(profile_enterprise1.owner).to eq original_owner
expect(profile_enterprise2.owner).to eq original_owner
end
it "cuts down the list of enterprises displayed when error received on bulk update" do
EnterpriseSet.any_instance.stub(:save) { false }
profile_enterprise1.enterprise_roles.build(user: new_owner).save
controller.stub spree_current_user: new_owner
bulk_enterprise_params = { enterprise_set: { collection_attributes: { '0' => { id: profile_enterprise1.id, visible: 'false' } } } }
spree_put :bulk_update, bulk_enterprise_params
expect(assigns(:enterprise_set).collection).to eq [profile_enterprise1]
end
end
context "as super admin" do

View File

@@ -6,8 +6,8 @@ module Api
include Spree::Api::TestingSupport::Helpers
render_views
let!(:oc1) { FactoryGirl.create(:order_cycle) }
let!(:oc2) { FactoryGirl.create(:order_cycle) }
let!(:oc1) { FactoryGirl.create(:simple_order_cycle) }
let!(:oc2) { FactoryGirl.create(:simple_order_cycle) }
let(:coordinator) { oc1.coordinator }
let(:attributes) { [:id, :name, :suppliers, :distributors] }
@@ -70,7 +70,7 @@ module Api
user.save!
user
end
let!(:order_cycle) { create(:order_cycle, suppliers: [oc_supplier], distributors: [oc_distributor]) }
let!(:order_cycle) { create(:simple_order_cycle, suppliers: [oc_supplier], distributors: [oc_distributor]) }
context "as the user of a supplier to an order cycle" do
before :each do

View File

@@ -1,26 +1,32 @@
require 'spec_helper'
describe BaseController do
let(:oc) { mock_model(OrderCycle) }
let(:order) { mock_model(Spree::Order) }
let(:oc) { mock_model(OrderCycle) }
let(:hub) { mock_model(Enterprise, ready_for_checkout?: true) }
let(:order) { mock_model(Spree::Order, distributor: hub) }
controller(BaseController) do
def index
render text: ""
end
end
it "redirects to home with message if order cycle is expired" do
controller.stub(:current_order_cycle).and_return oc
controller.stub(:current_order).and_return order
order.stub(:empty!)
order.stub(:set_order_cycle!)
oc.stub(:closed?).and_return true
controller.stub(:current_order_cycle).and_return(oc)
controller.stub(:current_order).and_return(order)
oc.stub(:closed?).and_return(true)
order.should_receive(:empty!)
order.should_receive(:set_order_cycle!).with(nil)
get :index
session[:expired_order_cycle_id].should == oc.id
response.should redirect_to root_url
flash[:info].should == "The order cycle you've selected has just closed. Please try again!"
end
it "loads active_distributors" do
Enterprise.should_receive(:distributors_with_active_order_cycles)
controller.load_active_distributors
Enterprise.stub(:distributors_with_active_order_cycles) { 'active distributors' }
controller.load_active_distributors.should == 'active distributors'
end
end

View File

@@ -2,7 +2,7 @@ require 'spec_helper'
describe CheckoutController do
let(:distributor) { double(:distributor) }
let(:order_cycle) { create(:order_cycle) }
let(:order_cycle) { create(:simple_order_cycle) }
let(:order) { create(:order) }
before do
order.stub(:checkout_allowed?).and_return true
@@ -20,6 +20,20 @@ describe CheckoutController do
response.should redirect_to shop_path
end
it "redirects home with message if hub is not ready for checkout" do
distributor.stub(:ready_for_checkout?) { false }
order.stub(distributor: distributor, order_cycle: order_cycle)
controller.stub(:current_order).and_return(order)
order.should_receive(:empty!)
order.should_receive(:set_distribution!).with(nil, nil)
get :edit
response.should redirect_to root_url
flash[:info].should == "The hub you have selected is temporarily closed for orders. Please try again later."
end
it "redirects to the shop when no line items are present" do
controller.stub(:current_distributor).and_return(distributor)
controller.stub(:current_order_cycle).and_return(order_cycle)

View File

@@ -1,15 +0,0 @@
require 'spec_helper'
describe Devise::ConfirmationsController do
context "after confirmation" do
before do
e = create(:enterprise, confirmed_at: nil)
@request.env["devise.mapping"] = Devise.mappings[:enterprise]
spree_get :show, confirmation_token: e.confirmation_token
end
it "should redirect to admin root" do
expect(response).to redirect_to spree.admin_path
end
end
end

View File

@@ -0,0 +1,42 @@
require 'spec_helper'
describe EnterpriseConfirmationsController do
include AuthenticationWorkflow
let!(:user) { create_enterprise_user( enterprise_limit: 10 ) }
let!(:unconfirmed_enterprise) { create(:distributor_enterprise, confirmed_at: nil, owner: user) }
let!(:confirmed_enterprise) { create(:distributor_enterprise, owner: user) }
let!(:unowned_enterprise) { create(:distributor_enterprise) }
before do
controller.stub spree_current_user: user
@request.env["devise.mapping"] = Devise.mappings[:enterprise]
end
context "confirming an enterprise" do
it "that has already been confirmed" do
spree_get :show, confirmation_token: confirmed_enterprise.confirmation_token
expect(response).to redirect_to spree.admin_path
expect(flash[:error]).to eq I18n.t('devise.enterprise_confirmations.enterprise.not_confirmed')
end
it "that has not already been confirmed" do
spree_get :show, confirmation_token: unconfirmed_enterprise.confirmation_token
expect(response).to redirect_to spree.admin_path
expect(flash[:success]).to eq I18n.t('devise.enterprise_confirmations.enterprise.confirmed')
end
end
context "requesting confirmation instructions to be resent" do
it "when the user owns the enterprise" do
spree_post :create, { enterprise: { id: unconfirmed_enterprise.id, email: unconfirmed_enterprise.email } }
expect(response).to redirect_to spree.admin_path
expect(flash[:success]).to eq I18n.t('devise.enterprise_confirmations.enterprise.confirmation_sent')
end
it "when the user does not own the enterprise" do
spree_post :create, { enterprise: { id: unowned_enterprise.id, email: unowned_enterprise.email } }
expect(response).to redirect_to spree.unauthorized_path
expect(flash[:error]).to eq "Authorization Failure"
end
end
end

View File

@@ -54,8 +54,8 @@ describe EnterprisesController do
describe "shopping for a distributor" do
before(:each) do
@current_distributor = create(:distributor_enterprise)
@distributor = create(:distributor_enterprise)
@current_distributor = create(:distributor_enterprise, with_payment_and_shipping: true)
@distributor = create(:distributor_enterprise, with_payment_and_shipping: true)
@order_cycle1 = create(:simple_order_cycle, distributors: [@distributor])
@order_cycle2 = create(:simple_order_cycle, distributors: [@distributor])
controller.current_order(true).distributor = @current_distributor
@@ -110,19 +110,21 @@ describe EnterprisesController do
end
end
describe "BaseController: handling order cycles closing mid-order" do
it "clears the order and displays an expiry message" do
oc = double(:order_cycle, id: 123, closed?: true)
controller.stub(:current_order_cycle) { oc }
context "checking permalink availability" do
# let(:enterprise) { create(:enterprise, permalink: 'enterprise_permalink') }
order = double(:order)
order.should_receive(:empty!)
order.should_receive(:set_order_cycle!).with(nil)
controller.stub(:current_order) { order }
it "responds with status of 200 when the route does not exist" do
spree_get :check_permalink, { permalink: 'some_nonexistent_route', format: :js }
expect(response.status).to be 200
end
spree_get :index
session[:expired_order_cycle_id].should == 123
response.should redirect_to root_url
it "responds with status of 409 when the permalink matches an existing route" do
# spree_get :check_permalink, { permalink: 'enterprise_permalink', format: :js }
# expect(response.status).to be 409
spree_get :check_permalink, { permalink: 'map', format: :js }
expect(response.status).to be 409
spree_get :check_permalink, { permalink: '', format: :js }
expect(response.status).to be 409
end
end
end

View File

@@ -6,7 +6,7 @@ describe HomeController do
let!(:invisible_distributor) { create(:distributor_enterprise, visible: false) }
before do
Enterprise.stub(:distributors_with_active_order_cycles).and_return [distributor]
Enterprise.stub(:distributors_with_active_order_cycles) { [distributor] }
end
it "sets active distributors" do

View File

@@ -2,7 +2,12 @@ require 'spec_helper'
describe MapController do
it "loads active distributors" do
Enterprise.should_receive(:distributors_with_active_order_cycles)
active_distributors = double(:distributors)
Enterprise.stub(:distributors_with_active_order_cycles) { active_distributors }
get :index
assigns(:active_distributors).should == active_distributors
end
end

View File

@@ -4,8 +4,8 @@ describe ProducersController do
let!(:distributor) { create(:distributor_enterprise) }
before do
Enterprise.stub(:distributors_with_active_order_cycles).and_return [distributor]
Enterprise.stub(:all).and_return [distributor]
Enterprise.stub(:distributors_with_active_order_cycles) { [distributor] }
Enterprise.stub(:all).and_return([distributor])
end
it "sets active distributors" do

View File

@@ -16,40 +16,40 @@ describe ShopController do
describe "Selecting order cycles" do
it "should select an order cycle when only one order cycle is open" do
oc1 = create(:order_cycle, distributors: [d])
oc1 = create(:simple_order_cycle, distributors: [d])
spree_get :show
controller.current_order_cycle.should == oc1
end
it "should not set an order cycle when multiple order cycles are open" do
oc1 = create(:order_cycle, distributors: [d])
oc2 = create(:order_cycle, distributors: [d])
oc1 = create(:simple_order_cycle, distributors: [d])
oc2 = create(:simple_order_cycle, distributors: [d])
spree_get :show
controller.current_order_cycle.should == nil
end
it "should allow the user to post to select the current order cycle" do
oc1 = create(:order_cycle, distributors: [d])
oc2 = create(:order_cycle, distributors: [d])
oc1 = create(:simple_order_cycle, distributors: [d])
oc2 = create(:simple_order_cycle, distributors: [d])
spree_post :order_cycle, order_cycle_id: oc2.id
response.should be_success
controller.current_order_cycle.should == oc2
end
context "RABL tests" do
render_views
render_views
it "should return the order cycle details when the oc is selected" do
oc1 = create(:order_cycle, distributors: [d])
oc2 = create(:order_cycle, distributors: [d])
oc1 = create(:simple_order_cycle, distributors: [d])
oc2 = create(:simple_order_cycle, distributors: [d])
spree_post :order_cycle, order_cycle_id: oc2.id
response.should be_success
response.body.should have_content oc2.id
response.body.should have_content oc2.id
end
it "should return the current order cycle when hit with GET" do
oc1 = create(:order_cycle, distributors: [d])
oc1 = create(:simple_order_cycle, distributors: [d])
controller.stub(:current_order_cycle).and_return oc1
spree_get :order_cycle
response.body.should have_content oc1.id
@@ -57,10 +57,10 @@ describe ShopController do
end
it "should not allow the user to select an invalid order cycle" do
oc1 = create(:order_cycle, distributors: [d])
oc2 = create(:order_cycle, distributors: [d])
oc3 = create(:order_cycle, distributors: [create(:distributor_enterprise)])
oc1 = create(:simple_order_cycle, distributors: [d])
oc2 = create(:simple_order_cycle, distributors: [d])
oc3 = create(:simple_order_cycle, distributors: [create(:distributor_enterprise)])
spree_post :order_cycle, order_cycle_id: oc3.id
response.status.should == 404
controller.current_order_cycle.should == nil
@@ -71,57 +71,74 @@ describe ShopController do
describe "producers/suppliers" do
let(:supplier) { create(:supplier_enterprise) }
let(:product) { create(:product, supplier: supplier) }
let(:order_cycle) { create(:order_cycle, distributors: [d], coordinator: create(:distributor_enterprise)) }
let(:order_cycle) { create(:simple_order_cycle, distributors: [d], coordinator: create(:distributor_enterprise)) }
before do
exchange = Exchange.find(order_cycle.exchanges.to_enterprises(d).outgoing.first.id)
exchange = Exchange.find(order_cycle.exchanges.to_enterprises(d).outgoing.first.id)
exchange.variants << product.master
end
end
describe "returning products" do
let(:product) { create(:product) }
let(:order_cycle) { create(:order_cycle, distributors: [d], coordinator: create(:distributor_enterprise)) }
let(:exchange) { Exchange.find(order_cycle.exchanges.to_enterprises(d).outgoing.first.id) }
let(:order_cycle) { create(:simple_order_cycle, distributors: [d], coordinator: create(:distributor_enterprise)) }
let(:exchange) { Exchange.find(order_cycle.exchanges.to_enterprises(d).outgoing.first.id) }
before do
exchange.variants << product.master
describe "requests and responses" do
let(:product) { create(:product) }
before do
exchange.variants << product.master
end
it "returns products via json" do
controller.stub(:current_order_cycle).and_return order_cycle
xhr :get, :products
response.should be_success
end
it "does not return products if no order_cycle is selected" do
controller.stub(:current_order_cycle).and_return nil
xhr :get, :products
response.status.should == 404
response.body.should be_empty
end
end
it "returns products via json" do
controller.stub(:current_order_cycle).and_return order_cycle
xhr :get, :products
response.should be_success
end
describe "sorting" do
let(:t1) { create(:taxon) }
let(:t2) { create(:taxon) }
let!(:p1) { create(:product, name: "abc", primary_taxon_id: t2.id) }
let!(:p2) { create(:product, name: "def", primary_taxon_id: t1.id) }
let!(:p3) { create(:product, name: "ghi", primary_taxon_id: t2.id) }
let!(:p4) { create(:product, name: "jkl", primary_taxon_id: t1.id) }
it "alphabetizes products" do
p1 = create(:product, name: "abc")
p2 = create(:product, name: "def")
exchange.variants << p1.master
exchange.variants << p2.master
controller.stub(:current_order_cycle).and_return order_cycle
xhr :get, :products
assigns[:products].should == [p1, p2, product].sort_by{|p| p.name }
end
before do
exchange.variants << p1.master
exchange.variants << p2.master
exchange.variants << p3.master
exchange.variants << p4.master
end
it "does not return products if no order_cycle is selected" do
controller.stub(:current_order_cycle).and_return nil
xhr :get, :products
response.status.should == 404
response.body.should be_empty
end
it "sorts products by the distributor's preferred taxon list" do
d.stub(:preferred_shopfront_taxon_order) {"#{t1.id},#{t2.id}"}
controller.stub(:current_order_cycle).and_return order_cycle
xhr :get, :products
assigns[:products].should == [p2, p4, p1, p3]
end
it "scopes variants for a product to the order cycle and distributor" do
controller.stub(:current_order_cycle).and_return order_cycle
controller.stub(:current_distributor).and_return d
Spree::Product.any_instance.should_receive(:variants_for).with(order_cycle, d).and_return(m = double())
m.stub(:in_stock).and_return []
xhr :get, :products
it "alphabetizes products by name when taxon list is not set" do
d.stub(:preferred_shopfront_taxon_order) {""}
controller.stub(:current_order_cycle).and_return order_cycle
xhr :get, :products
assigns[:products].should == [p1, p2, p3, p4]
end
end
context "RABL tests" do
render_views
let(:product) { create(:product) }
before do
exchange.variants << product.master
controller.stub(:current_order_cycle).and_return order_cycle
end
it "only returns products for the current order cycle" do

View File

@@ -12,4 +12,27 @@ describe Spree::Admin::BaseController do
get :index
response.should redirect_to root_path(anchor: "login?after_login=/anonymous")
end
describe "displaying error messages for active distributors not ready for checkout" do
it "generates an error message when there is one distributor" do
distributor = double(:distributor, name: 'My Hub')
controller.
send(:active_distributors_not_ready_for_checkout_message, [distributor]).
should ==
"The hub My Hub is listed in an active order cycle, " +
"but does not have valid shipping and payment methods. " +
"Until you set these up, customers will not be able to shop at this hub."
end
it "generates an error message when there are several distributors" do
d1 = double(:distributor, name: 'Hub One')
d2 = double(:distributor, name: 'Hub Two')
controller.
send(:active_distributors_not_ready_for_checkout_message, [d1, d2]).
should ==
"The hubs Hub One, Hub Two are listed in an active order cycle, " +
"but do not have valid shipping and payment methods. " +
"Until you set these up, customers will not be able to shop at these hubs."
end
end
end

View File

@@ -0,0 +1,43 @@
require 'spec_helper'
describe Spree::Admin::OverviewController do
include AuthenticationWorkflow
context "loading overview" do
let(:user) { create_enterprise_user(enterprise_limit: 2) }
before do
controller.stub spree_current_user: user
end
context "when user own only one enterprise" do
let!(:enterprise) { create(:distributor_enterprise, owner: user) }
it "renders the single enterprise dashboard" do
spree_get :index
response.should render_template "single_enterprise_dashboard"
end
context "when the enterprise sells property has not been set" do
before do
enterprise.sells = "unspecified"
enterprise.save
end
it "renders the welcome page" do
spree_get :index
response.should render_template "welcome"
end
end
end
context "when user owns multiple enterprises" do
let!(:enterprise1) { create(:distributor_enterprise, owner: user) }
let!(:enterprise2) { create(:distributor_enterprise, owner: user) }
it "renders the multi enterprise dashboard" do
spree_get :index
response.should render_template "multi_enterprise_dashboard"
end
end
end
end

View File

@@ -0,0 +1,35 @@
require 'spec_helper'
describe Spree::Admin::SearchController do
include AuthenticationWorkflow
context "Distributor Enterprise User" do
let!(:owner) { create_enterprise_user( email: "test1@email.com" ) }
let!(:manager) { create_enterprise_user( email: "test2@email.com" ) }
let!(:random) { create_enterprise_user( email: "test3@email.com" ) }
let!(:enterprise) { create(:enterprise, owner: owner, users: [owner, manager]) }
before { login_as_enterprise_user [enterprise] }
describe 'searching for known users' do
describe "when search query is not an exact match" do
before do
spree_get :known_users, q: "test"
end
it "returns a list of users that I share management of enteprises with" do
expect(assigns(:users)).to include owner, manager
expect(assigns(:users)).to_not include random
end
end
describe "when search query exactly matches the email of a user in the system" do
before do
spree_get :known_users, q: "test3@email.com"
end
it "returns that user, regardless of the relationship between the two users" do
expect(assigns(:users)).to eq [random]
end
end
end
end
end

View File

@@ -1,8 +1,11 @@
require 'spec_helper'
require 'spree/api/testing_support/helpers'
require 'support/request/authentication_workflow'
describe Spree::CheckoutController do
include AuthenticationWorkflow
context "After completing an order" do
it "should create a new empty order" do
controller.current_order(true)
@@ -34,6 +37,18 @@ describe Spree::CheckoutController do
controller.current_order.token.should == order.token
session[:access_token].should == order.token
end
end
context "rendering edit from within spree for the current checkout state" do
let!(:order) { controller.current_order(true) }
let!(:line_item) { create(:line_item, order: order) }
let!(:user) { create_enterprise_user }
it "redirects to the OFN checkout page" do
controller.stub(:skip_state_validation?) { true }
controller.stub(:spree_current_user) { user }
spree_get :edit
response.should redirect_to checkout_path
end
end
end

View File

@@ -26,30 +26,18 @@ describe Spree::OrdersController do
response.should redirect_to shop_path
end
it "selects distributors" do
d = create(:distributor_enterprise)
p = create(:product, :distributors => [d])
spree_get :select_distributor, :id => d.id
response.should be_redirect
order = subject.current_order(false)
order.distributor.should == d
end
it "deselects distributors" do
d = create(:distributor_enterprise)
p = create(:product, :distributors => [d])
it "redirects home with message if hub is not ready for checkout" do
order = subject.current_order(true)
order.distributor = d
order.save!
distributor.stub(:ready_for_checkout?) { false }
order.stub(distributor: distributor, order_cycle: order_cycle)
spree_get :deselect_distributor
response.should be_redirect
order.should_receive(:empty!)
order.should_receive(:set_distribution!).with(nil, nil)
order.reload
order.distributor.should be_nil
spree_get :edit
response.should redirect_to root_url
flash[:info].should == "The hub you have selected is temporarily closed for orders. Please try again later."
end
context "adding a group buy product to the cart" do

View File

@@ -89,9 +89,15 @@ FactoryGirl.define do
incoming false
end
factory :variant_override, :class => VariantOverride do
price 77.77
count_on_hand 11111
end
factory :enterprise, :class => Enterprise do
owner { FactoryGirl.create :user }
sequence(:name) { |n| "Enterprise #{n}" }
sequence(:permalink) { |n| "enterprise#{n}" }
sells 'any'
description 'enterprise'
long_description '<p>Hello, world!</p><p>This is a paragraph.</p>'
@@ -108,6 +114,17 @@ FactoryGirl.define do
factory :distributor_enterprise, :parent => :enterprise do
is_primary_producer false
sells "any"
ignore do
with_payment_and_shipping false
end
after(:create) do |enterprise, proxy|
if proxy.with_payment_and_shipping
create(:payment_method, distributors: [enterprise])
create(:shipping_method, distributors: [enterprise])
end
end
end
factory :enterprise_relationship do
@@ -120,6 +137,7 @@ FactoryGirl.define do
name 'Enterprise group'
description 'this is a group'
on_front_page false
address { FactoryGirl.build(:address) }
end
sequence(:calculator_amount)

View File

@@ -5,7 +5,11 @@ feature "Authentication", js: true do
let(:user) { create(:user, password: "password", password_confirmation: "password") }
scenario "logging into admin redirects home, then back to admin" do
visit spree.admin_path
# This is the first admin spec, so give a little extra load time for slow systems
Capybara.using_wait_time(60) do
visit spree.admin_path
end
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_login_button

View File

@@ -5,20 +5,16 @@ feature %q{
I want to be able to manage orders in bulk
} , js: true do
include AuthenticationWorkflow
include AuthorizationHelpers
include WebHelper
after { Warden.test_reset! }
stub_authorization!
context "listing orders" do
before :each do
admin_user = quick_login_as_admin
login_to_admin_section
end
it "displays a message when number of line items is zero" do
visit '/admin/orders/bulk_management'
page.should have_text "No orders found."
end
context "displaying the list of line items" do
@@ -172,119 +168,159 @@ feature %q{
end
context "using drop down seletors" do
let!(:oc1) { FactoryGirl.create(:order_cycle) }
let!(:oc2) { FactoryGirl.create(:order_cycle) }
let!(:s1) { oc1.suppliers.first }
let!(:s2) { oc2.suppliers.last }
let!(:d1) { oc1.distributors.first }
let!(:d2) { oc2.distributors.last }
let!(:p1) { FactoryGirl.create(:product, supplier: s1) }
let!(:p2) { FactoryGirl.create(:product, supplier: s2) }
let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d1, order_cycle: oc1 ) }
let!(:o2) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d2, order_cycle: oc2 ) }
let!(:li1) { FactoryGirl.create(:line_item, order: o1, product: p1 ) }
let!(:li2) { FactoryGirl.create(:line_item, order: o2, product: p2 ) }
context "supplier filter" do
let!(:s1) { create(:supplier_enterprise) }
let!(:s2) { create(:supplier_enterprise) }
let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now ) }
let!(:li1) { FactoryGirl.create(:line_item, order: o1, product: create(:product, supplier: s1) ) }
let!(:li2) { FactoryGirl.create(:line_item, order: o1, product: create(:product, supplier: s2) ) }
before :each do
visit '/admin/orders/bulk_management'
before :each do
visit '/admin/orders/bulk_management'
end
it "displays a select box for producers, which filters line items by the selected supplier" do
supplier_names = ["All"]
Enterprise.is_primary_producer.each{ |e| supplier_names << e.name }
find("div.select2-container#s2id_supplier_filter").click
supplier_names.each { |sn| page.should have_selector "div.select2-drop-active ul.select2-results li", text: sn }
find("div.select2-container#s2id_supplier_filter").click
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
select2_select s1.name, from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}"
end
it "displays all line items when 'All' is selected from supplier filter" do
select2_select s1.name, from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select "All", from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
end
end
it "displays a select box for producers, which filters line items by the selected supplier" do
supplier_names = ["All"]
Enterprise.is_primary_producer.each{ |e| supplier_names << e.name }
find("div.select2-container#s2id_supplier_filter").click
supplier_names.each { |sn| page.should have_selector "div.select2-drop-active ul.select2-results li", text: sn }
find("div.select2-container#s2id_supplier_filter").click
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
select2_select s1.name, from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}"
context "distributor filter" do
let!(:d1) { create(:distributor_enterprise) }
let!(:d2) { create(:distributor_enterprise) }
let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d1 ) }
let!(:o2) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d2 ) }
let!(:li1) { FactoryGirl.create(:line_item, order: o1 ) }
let!(:li2) { FactoryGirl.create(:line_item, order: o2 ) }
before :each do
visit '/admin/orders/bulk_management'
end
it "displays a select box for distributors, which filters line items by the selected distributor" do
distributor_names = ["All"]
Enterprise.is_distributor.each{ |e| distributor_names << e.name }
find("div.select2-container#s2id_distributor_filter").click
distributor_names.each { |dn| page.should have_selector "div.select2-drop-active ul.select2-results li", text: dn }
find("div.select2-container#s2id_distributor_filter").click
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
select2_select d1.name, from: "distributor_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
end
it "displays all line items when 'All' is selected from distributor filter" do
select2_select d1.name, from: "distributor_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select "All", from: "distributor_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
end
end
it "displays all line items when 'All' is selected from supplier filter" do
select2_select s1.name, from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select "All", from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
context "order_cycle filter" do
let!(:oc1) { FactoryGirl.create(:simple_order_cycle ) }
let!(:oc2) { FactoryGirl.create(:simple_order_cycle ) }
let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, order_cycle: oc1 ) }
let!(:o2) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, order_cycle: oc2 ) }
let!(:li1) { FactoryGirl.create(:line_item, order: o1 ) }
let!(:li2) { FactoryGirl.create(:line_item, order: o2 ) }
before :each do
visit '/admin/orders/bulk_management'
end
it "displays a select box for order cycles, which filters line items by the selected order cycle" do
order_cycle_names = ["All"]
OrderCycle.all.each{ |oc| order_cycle_names << oc.name }
find("div.select2-container#s2id_order_cycle_filter").click
order_cycle_names.each { |ocn| page.should have_selector "div.select2-drop-active ul.select2-results li", text: ocn }
find("div.select2-container#s2id_order_cycle_filter").click
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
select2_select oc1.name, from: "order_cycle_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
end
it "displays all line items when 'All' is selected from order_cycle filter" do
select2_select oc1.name, from: "order_cycle_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select "All", from: "order_cycle_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
end
end
it "displays a select box for distributors, which filters line items by the selected distributor" do
distributor_names = ["All"]
Enterprise.is_distributor.each{ |e| distributor_names << e.name }
find("div.select2-container#s2id_distributor_filter").click
distributor_names.each { |dn| page.should have_selector "div.select2-drop-active ul.select2-results li", text: dn }
find("div.select2-container#s2id_distributor_filter").click
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
select2_select d1.name, from: "distributor_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
end
context "combination of filters" do
let!(:s1) { create(:supplier_enterprise) }
let!(:s2) { create(:supplier_enterprise) }
let!(:d1) { create(:distributor_enterprise) }
let!(:d2) { create(:distributor_enterprise) }
let!(:oc1) { FactoryGirl.create(:simple_order_cycle, suppliers: [s1], distributors: [d1] ) }
let!(:oc2) { FactoryGirl.create(:simple_order_cycle, suppliers: [s2], distributors: [d2] ) }
let!(:p1) { FactoryGirl.create(:product, supplier: s1) }
let!(:p2) { FactoryGirl.create(:product, supplier: s2) }
let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d1, order_cycle: oc1 ) }
let!(:o2) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d2, order_cycle: oc2 ) }
let!(:li1) { FactoryGirl.create(:line_item, order: o1, product: p1 ) }
let!(:li2) { FactoryGirl.create(:line_item, order: o2, product: p2 ) }
it "displays all line items when 'All' is selected from distributor filter" do
select2_select d1.name, from: "distributor_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select "All", from: "distributor_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
end
before :each do
visit '/admin/orders/bulk_management'
end
it "displays a select box for order cycles, which filters line items by the selected order cycle" do
order_cycle_names = ["All"]
OrderCycle.all.each{ |oc| order_cycle_names << oc.name }
find("div.select2-container#s2id_order_cycle_filter").click
order_cycle_names.each { |ocn| page.should have_selector "div.select2-drop-active ul.select2-results li", text: ocn }
find("div.select2-container#s2id_order_cycle_filter").click
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
select2_select oc1.name, from: "order_cycle_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
end
it "allows filters to be used in combination" do
select2_select oc1.name, from: "order_cycle_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select d1.name, from: "distributor_filter"
select2_select s1.name, from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select d2.name, from: "distributor_filter"
select2_select s2.name, from: "supplier_filter"
page.should_not have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select oc2.name, from: "order_cycle_filter"
page.should_not have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
end
it "displays all line items when 'All' is selected from order_cycle filter" do
select2_select oc1.name, from: "order_cycle_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select "All", from: "order_cycle_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
end
it "allows filters to be used in combination" do
select2_select oc1.name, from: "order_cycle_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select d1.name, from: "distributor_filter"
select2_select s1.name, from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select d2.name, from: "distributor_filter"
select2_select s2.name, from: "supplier_filter"
page.should_not have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
select2_select oc2.name, from: "order_cycle_filter"
page.should_not have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
end
it "displays a 'Clear All' button which sets all select filters to 'All'" do
select2_select oc1.name, from: "order_cycle_filter"
select2_select d1.name, from: "distributor_filter"
select2_select s1.name, from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
page.should have_button "Clear All"
click_button "Clear All"
page.should have_selector "div#s2id_order_cycle_filter a.select2-choice", text: "All"
page.should have_selector "div#s2id_supplier_filter a.select2-choice", text: "All"
page.should have_selector "div#s2id_distributor_filter a.select2-choice", text: "All"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
it "displays a 'Clear All' button which sets all select filters to 'All'" do
select2_select oc1.name, from: "order_cycle_filter"
select2_select d1.name, from: "distributor_filter"
select2_select s1.name, from: "supplier_filter"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should_not have_selector "tr#li_#{li2.id}", visible: true
page.should have_button "Clear All"
click_button "Clear All"
page.should have_selector "div#s2id_order_cycle_filter a.select2-choice", text: "All"
page.should have_selector "div#s2id_supplier_filter a.select2-choice", text: "All"
page.should have_selector "div#s2id_distributor_filter a.select2-choice", text: "All"
page.should have_selector "tr#li_#{li1.id}", visible: true
page.should have_selector "tr#li_#{li2.id}", visible: true
end
end
end

View File

@@ -25,7 +25,7 @@ feature %q{
it "displays a message when number of products is zero" do
visit '/admin/products/bulk_edit'
expect(page).to have_text "No products found."
expect(page).to have_text "No products yet. Why don't you add some?"
end
it "displays a select box for suppliers, with the appropriate supplier selected" do
@@ -37,8 +37,8 @@ feature %q{
visit '/admin/products/bulk_edit'
expect(page).to have_select "producer", with_options: [s1.name,s2.name,s3.name], selected: s2.name
expect(page).to have_select "producer", with_options: [s1.name,s2.name,s3.name], selected: s3.name
expect(page).to have_select "producer_id", with_options: [s1.name,s2.name,s3.name], selected: s2.name
expect(page).to have_select "producer_id", with_options: [s1.name,s2.name,s3.name], selected: s3.name
end
it "displays a date input for available_on for each product, formatted to yyyy-mm-dd hh:mm:ss" do
@@ -267,7 +267,7 @@ feature %q{
fill_in "variant_price", with: "4.0"
fill_in "variant_on_hand", with: "10"
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
updated_variant = Spree::Variant.where(deleted_at: nil).last
expect(updated_variant.display_name).to eq "Case of 12 Bottles"
@@ -302,25 +302,25 @@ feature %q{
within "tr#p_#{p.id}" do
expect(page).to have_field "product_name", with: p.name
expect(page).to have_select "producer", selected: s1.name
expect(page).to have_select "producer_id", selected: s1.name
expect(page).to have_field "available_on", with: p.available_on.strftime("%F %T")
expect(page).to have_field "price", with: "10.0"
expect(page).to have_selector "div#s2id_p#{p.id}_category a.select2-choice"
expect(page).to have_selector "div#s2id_p#{p.id}_category_id a.select2-choice"
expect(page).to have_select "variant_unit_with_scale", selected: "Volume (L)"
expect(page).to have_field "on_hand", with: "6"
fill_in "product_name", with: "Big Bag Of Potatoes"
select s2.name, :from => 'producer'
select s2.name, :from => 'producer_id'
fill_in "available_on", with: (3.days.ago.beginning_of_day).strftime("%F %T")
fill_in "price", with: "20"
select "Weight (kg)", from: "variant_unit_with_scale"
select2_select t1.name, from: "p#{p.id}_category"
select2_select t1.name, from: "p#{p.id}_category_id"
fill_in "on_hand", with: "18"
fill_in "display_as", with: "Big Bag"
end
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "Big Bag Of Potatoes"
@@ -347,7 +347,7 @@ feature %q{
fill_in "variant_unit_name", with: "loaf"
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.variant_unit).to eq "items"
@@ -370,7 +370,7 @@ feature %q{
fill_in "variant_unit_value_with_description", with: '123 abc'
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.variant_unit).to eq "weight"
@@ -395,7 +395,7 @@ feature %q{
fill_in "master_unit_value_with_description", with: '123 abc'
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.variant_unit).to eq 'weight'
@@ -443,7 +443,7 @@ feature %q{
expect(page).to have_selector "span[name='on_hand']", text: "10"
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
v.reload
expect(v.price).to eq 4.0
@@ -467,7 +467,7 @@ feature %q{
fill_in "variant_price", with: "10.0"
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
v.reload
expect(v.price).to eq 10.0
@@ -484,21 +484,21 @@ feature %q{
fill_in "product_name", with: "new name 1"
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "new name 1"
fill_in "product_name", with: "new name 2"
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "new name 2"
fill_in "product_name", with: "original name"
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "original name"
end
@@ -514,7 +514,7 @@ feature %q{
fill_in "product_name", :with => "new product name"
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "new product name"
end
@@ -527,7 +527,7 @@ feature %q{
visit '/admin/products/bulk_edit'
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "No changes to save."
expect(page.find("#status-message")).to have_content "No changes to save."
end
end
@@ -546,7 +546,7 @@ feature %q{
fill_in "product_name", :with => "new product1"
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p1.reload
expect(p1.name).to eq "new product1"
end
@@ -654,13 +654,13 @@ feature %q{
end
expect(page).to have_selector "a.clone-product", :count => 4
expect(page).to have_field "product_name", with: "COPY OF #{p1.name}"
expect(page).to have_select "producer", selected: "#{p1.supplier.name}"
expect(page).to have_select "producer_id", selected: "#{p1.supplier.name}"
visit '/admin/products/bulk_edit'
expect(page).to have_selector "a.clone-product", :count => 4
expect(page).to have_field "product_name", with: "COPY OF #{p1.name}"
expect(page).to have_select "producer", selected: "#{p1.supplier.name}"
expect(page).to have_select "producer_id", selected: "#{p1.supplier.name}"
end
end
end
@@ -764,8 +764,8 @@ feature %q{
it "shows only suppliers that I manage or have permission to" do
visit '/admin/products/bulk_edit'
expect(page).to have_select 'producer', with_options: [supplier_managed1.name, supplier_managed2.name, supplier_permitted.name], selected: supplier_managed1.name
expect(page).to have_no_select 'producer', with_options: [supplier_unmanaged.name]
expect(page).to have_select 'producer_id', with_options: [supplier_managed1.name, supplier_managed2.name, supplier_permitted.name], selected: supplier_managed1.name
expect(page).to have_no_select 'producer_id', with_options: [supplier_unmanaged.name]
end
it "shows inactive products that I supply" do
@@ -807,13 +807,13 @@ feature %q{
within "tr#p_#{p.id}" do
expect(page).to have_field "product_name", with: p.name
expect(page).to have_select "producer", selected: supplier_permitted.name
expect(page).to have_select "producer_id", selected: supplier_permitted.name
expect(page).to have_field "available_on", with: p.available_on.strftime("%F %T")
expect(page).to have_field "price", with: "10.0"
expect(page).to have_field "on_hand", with: "6"
fill_in "product_name", with: "Big Bag Of Potatoes"
select(supplier_managed2.name, :from => 'producer')
select supplier_managed2.name, :from => 'producer_id'
fill_in "available_on", with: (3.days.ago.beginning_of_day).strftime("%F %T")
fill_in "price", with: "20"
select "Weight (kg)", from: "variant_unit_with_scale"
@@ -822,7 +822,7 @@ feature %q{
end
click_button 'Save Changes'
expect(page.find("#update-status-message")).to have_content "Changes saved."
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "Big Bag Of Potatoes"

View File

@@ -15,28 +15,33 @@ feature %q{
e = create(:enterprise)
group = create(:enterprise_group, enterprises: [e], on_front_page: true)
click_link 'Configuration'
click_link 'Enterprise Groups'
click_link 'Groups'
page.should have_selector 'td', text: group.name
page.should have_selector 'td', text: 'Y'
page.should have_selector 'td', text: e.name
end
scenario "creating a new enterprise group" do
scenario "creating a new enterprise group", js: true do
e1 = create(:enterprise)
e2 = create(:enterprise)
e3 = create(:enterprise)
click_link 'Configuration'
click_link 'Enterprise Groups'
click_link 'Groups'
click_link 'New Enterprise Group'
fill_in 'enterprise_group_name', with: 'EGEGEG'
fill_in 'enterprise_group_description', with: 'This is a description'
check 'enterprise_group_on_front_page'
select e1.name, from: 'enterprise_group_enterprise_ids'
select e2.name, from: 'enterprise_group_enterprise_ids'
select2_search e1.name, from: 'Enterprises'
select2_search e2.name, from: 'Enterprises'
click_link 'Contact'
fill_in 'enterprise_group_address_attributes_phone', with: '000'
fill_in 'enterprise_group_address_attributes_address1', with: 'My Street'
fill_in 'enterprise_group_address_attributes_city', with: 'Block'
fill_in 'enterprise_group_address_attributes_zipcode', with: '0000'
select2_search 'Australia', :from => 'Country'
select2_search 'Victoria', :from => 'State'
click_button 'Create'
page.should have_content 'Enterprise group "EGEGEG" has been successfully created!'
@@ -53,8 +58,7 @@ feature %q{
e2 = create(:enterprise)
eg = create(:enterprise_group, name: 'EGEGEG', on_front_page: true, enterprises: [e1, e2])
click_link 'Configuration'
click_link 'Enterprise Groups'
click_link 'Groups'
first("a.edit-enterprise-group").click
page.should have_field 'enterprise_group_name', with: 'EGEGEG'
@@ -80,8 +84,7 @@ feature %q{
eg1 = create(:enterprise_group, name: 'A')
eg2 = create(:enterprise_group, name: 'B')
click_link 'Configuration'
click_link 'Enterprise Groups'
click_link 'Groups'
page.all('td.name').map(&:text).should == ['A', 'B']
all("a.move-down").first.click
@@ -93,8 +96,7 @@ feature %q{
scenario "deleting an enterprise group", js: true do
eg = create(:enterprise_group, name: 'EGEGEG')
click_link 'Configuration'
click_link 'Enterprise Groups'
click_link 'Groups'
first("a.delete-resource").click
page.should have_no_content 'EGEGEG'

View File

@@ -42,13 +42,15 @@ feature %q{
check 'to add to order cycle'
check 'to manage products'
uncheck 'to manage products'
check 'to edit profile'
check 'to override variant details'
select 'Two', from: 'enterprise_relationship_child_id'
click_button 'Create'
page.should have_relationship e1, e2, ['to add to order cycle']
page.should have_relationship e1, e2, ['to add to order cycle', 'to override variant details', 'to edit profile']
er = EnterpriseRelationship.where(parent_id: e1, child_id: e2).first
er.should be_present
er.permissions.map(&:name).should == ['add_to_order_cycle']
er.permissions.map(&:name).sort.should == ['add_to_order_cycle', 'edit_profile', 'create_variant_overrides'].sort
end

View File

@@ -35,28 +35,63 @@ feature %q{
end
end
scenario "editing enterprises in bulk" do
s = create(:supplier_enterprise)
d = create(:distributor_enterprise, sells: 'none')
d_manager = create_enterprise_user
d_manager.enterprise_roles.build(enterprise: d).save
expect(d.owner).to_not eq d_manager
context "editing enterprises in bulk" do
let!(:s){ create(:supplier_enterprise) }
let!(:d){ create(:distributor_enterprise, sells: 'none') }
let!(:d_manager) { create_enterprise_user(enterprise_limit: 1) }
login_to_admin_section
click_link 'Enterprises'
within("tr.enterprise-#{d.id}") do
expect(page).to have_checked_field "enterprise_set_collection_attributes_0_visible"
uncheck "enterprise_set_collection_attributes_0_visible"
select 'any', from: "enterprise_set_collection_attributes_0_sells"
select d_manager.email, from: 'enterprise_set_collection_attributes_0_owner_id'
before do
d_manager.enterprise_roles.build(enterprise: d).save
expect(d.owner).to_not eq d_manager
end
context "without violating rules" do
before do
login_to_admin_section
click_link 'Enterprises'
end
it "updates the enterprises" do
within("tr.enterprise-#{d.id}") do
expect(page).to have_checked_field "enterprise_set_collection_attributes_0_visible"
uncheck "enterprise_set_collection_attributes_0_visible"
select 'any', from: "enterprise_set_collection_attributes_0_sells"
select d_manager.email, from: 'enterprise_set_collection_attributes_0_owner_id'
end
click_button "Update"
flash_message.should == 'Enterprises updated successfully'
distributor = Enterprise.find(d.id)
expect(distributor.visible).to eq false
expect(distributor.sells).to eq 'any'
expect(distributor.owner).to eq d_manager
end
end
context "with data that violates rules" do
let!(:second_distributor) { create(:distributor_enterprise, sells: 'none') }
before do
d_manager.enterprise_roles.build(enterprise: second_distributor).save
expect(d.owner).to_not eq d_manager
login_to_admin_section
click_link 'Enterprises'
end
it "does not update the enterprises and displays errors" do
within("tr.enterprise-#{d.id}") do
select d_manager.email, from: 'enterprise_set_collection_attributes_0_owner_id'
end
within("tr.enterprise-#{second_distributor.id}") do
select d_manager.email, from: 'enterprise_set_collection_attributes_1_owner_id'
end
click_button "Update"
flash_message.should == 'Update failed'
expect(page).to have_content "#{d_manager.email} is not permitted to own any more enterprises (limit is 1)."
second_distributor.reload
expect(second_distributor.owner).to_not eq d_manager
end
end
click_button "Update"
flash_message.should == 'Enterprises updated successfully'
distributor = Enterprise.find(d.id)
expect(distributor.visible).to eq false
expect(distributor.sells).to eq 'any'
expect(distributor.owner).to eq d_manager
end
scenario "viewing an enterprise" do
@@ -69,7 +104,7 @@ feature %q{
page.should have_content e.name
end
scenario "creating a new enterprise", js:true do
scenario "creating a new enterprise", js: true do
eg1 = create(:enterprise_group, name: 'eg1')
eg2 = create(:enterprise_group, name: 'eg2')
payment_method = create(:payment_method)
@@ -90,28 +125,23 @@ feature %q{
# Filling in details
fill_in 'enterprise_name', :with => 'Eaterprises'
# This call intermittently fails to complete, leaving the select2 box open obscuring the
# fields below it (which breaks the remainder of our specs). Calling it twice seems to
# solve the problem.
select2_search admin.email, from: 'Owner'
choose 'Any'
check "enterprise_payment_method_ids_#{payment_method.id}"
check "enterprise_shipping_method_ids_#{shipping_method.id}"
select2_search eg1.name, from: 'Groups'
select2_search admin.email, from: 'Owner'
fill_in 'enterprise_contact', :with => 'Kirsten or Ren'
fill_in 'enterprise_phone', :with => '0413 897 321'
fill_in 'enterprise_email', :with => 'info@eaterprises.com.au'
fill_in 'enterprise_website', :with => 'http://eaterprises.com.au'
fill_in 'enterprise_twitter', :with => '@eaterprises'
fill_in 'enterprise_facebook', :with => 'facebook.com/eaterprises'
fill_in 'enterprise_instagram', :with => 'eaterprises'
fill_in 'enterprise_abn', :with => '09812309823'
fill_in 'enterprise_acn', :with => ''
fill_in 'enterprise_address_attributes_address1', :with => '35 Ballantyne St'
fill_in 'enterprise_address_attributes_city', :with => 'Thornbury'
fill_in 'enterprise_address_attributes_zipcode', :with => '3072'
select2_search 'Australia', :from => 'Country'
select2_search 'Victoria', :from => 'State'
long_description = find :css, "text-angular div.ta-scroll-window div.ta-bind"
long_description.set 'Connecting farmers and eaters'
click_button 'Create'
flash_message.should == 'Enterprise "Eaterprises" has been successfully created!'
@@ -136,21 +166,26 @@ feature %q{
fill_in 'enterprise_name', :with => 'Eaterprises'
choose 'Own'
within (".side_menu") { click_link "Users" }
select2_search user.email, from: 'Owner'
click_link "About"
fill_in 'enterprise_description', :with => 'Connecting farmers and eaters'
long_description = find :css, "text-angular div.ta-scroll-window div.ta-bind"
long_description = find :css, "text-angular#enterprise_long_description div.ta-scroll-window div.ta-bind"
long_description.set 'This is an interesting long description'
# Check Angularjs switching of sidebar elements
click_link "Primary Details"
uncheck 'enterprise_is_primary_producer'
choose 'None'
page.should have_selector "#enterprise_fees", visible: false
page.should have_selector "#payment_methods", visible: false
page.should have_selector "#shipping_methods", visible: false
page.should_not have_selector "#enterprise_fees"
page.should_not have_selector "#payment_methods"
page.should_not have_selector "#shipping_methods"
check 'enterprise_is_primary_producer'
page.should have_selector "#enterprise_fees"
page.should have_selector "#payment_methods", visible: false
page.should have_selector "#shipping_methods", visible: false
page.should_not have_selector "#payment_methods"
page.should_not have_selector "#shipping_methods"
uncheck 'enterprise_is_primary_producer'
choose 'Own'
page.should have_selector "#enterprise_fees"
@@ -163,26 +198,38 @@ feature %q{
select2_search eg1.name, from: 'Groups'
click_link "Payment Methods"
page.should_not have_checked_field "enterprise_payment_method_ids_#{payment_method.id}"
page.should_not have_checked_field "enterprise_shipping_method_ids_#{shipping_method.id}"
check "enterprise_payment_method_ids_#{payment_method.id}"
click_link "Shipping Methods"
page.should_not have_checked_field "enterprise_shipping_method_ids_#{shipping_method.id}"
check "enterprise_shipping_method_ids_#{shipping_method.id}"
click_link "Contact"
fill_in 'enterprise_contact', :with => 'Kirsten or Ren'
fill_in 'enterprise_phone', :with => '0413 897 321'
fill_in 'enterprise_email', :with => 'info@eaterprises.com.au'
fill_in 'enterprise_website', :with => 'http://eaterprises.com.au'
click_link "Social"
fill_in 'enterprise_twitter', :with => '@eaterprises'
click_link "Business Details"
fill_in 'enterprise_abn', :with => '09812309823'
fill_in 'enterprise_acn', :with => ''
click_link "Address"
fill_in 'enterprise_address_attributes_address1', :with => '35 Ballantyne St'
fill_in 'enterprise_address_attributes_city', :with => 'Thornbury'
fill_in 'enterprise_address_attributes_zipcode', :with => '3072'
select2_search 'Australia', :from => 'Country'
select2_search 'Victoria', :from => 'State'
click_link "Shop Preferences"
shopfront_message = find :css, "text-angular#enterprise_preferred_shopfront_message div.ta-scroll-window div.ta-bind"
shopfront_message.set 'This is my shopfront message.'
click_button 'Update'
flash_message.should == 'Enterprise "Eaterprises" has been successfully updated!'
@@ -190,10 +237,20 @@ feature %q{
@enterprise.reload
expect(@enterprise.owner).to eq user
click_link "Payment Methods"
page.should have_checked_field "enterprise_payment_method_ids_#{payment_method.id}"
click_link "Shipping Methods"
page.should have_checked_field "enterprise_shipping_method_ids_#{shipping_method.id}"
page.should have_selector "a.list-item", text: enterprise_fee.name
click_link "Enterprise Fees"
page.should have_selector "td", text: enterprise_fee.name
click_link "About"
page.should have_content 'This is an interesting long description'
click_link "Shop Preferences"
page.should have_content 'This is my shopfront message.'
end
describe "producer properties" do
@@ -269,11 +326,14 @@ feature %q{
let(:supplier2) { create(:supplier_enterprise, name: 'Another Supplier') }
let(:distributor1) { create(:distributor_enterprise, name: 'First Distributor') }
let(:distributor2) { create(:distributor_enterprise, name: 'Another Distributor') }
let(:distributor3) { create(:distributor_enterprise, name: 'Yet Another Distributor') }
let(:enterprise_user) { create_enterprise_user }
let(:er) { create(:enterprise_relationship, parent: distributor3, child: distributor1, permissions_list: [:edit_profile]) }
before(:each) do
enterprise_user.enterprise_roles.build(enterprise: supplier1).save
enterprise_user.enterprise_roles.build(enterprise: distributor1).save
er
login_to_admin_as enterprise_user
end
@@ -291,10 +351,16 @@ feature %q{
expect(page).to_not have_select "enterprise_set_collection_attributes_0_sells"
end
within("tr.enterprise-#{distributor3.id}") do
expect(page).to have_content distributor3.name
expect(page).to have_unchecked_field "enterprise_set_collection_attributes_1_is_primary_producer"
expect(page).to_not have_select "enterprise_set_collection_attributes_1_sells"
end
within("tr.enterprise-#{supplier1.id}") do
expect(page).to have_content supplier1.name
expect(page).to have_checked_field "enterprise_set_collection_attributes_1_is_primary_producer"
expect(page).to_not have_select "enterprise_set_collection_attributes_1_sells"
expect(page).to have_checked_field "enterprise_set_collection_attributes_2_is_primary_producer"
expect(page).to_not have_select "enterprise_set_collection_attributes_2_sells"
end
expect(page).to_not have_content "supplier2.name"
@@ -350,20 +416,53 @@ feature %q{
# Then it should show me an error
expect(page).to_not have_content 'Enterprise "zzz" has been successfully created!'
expect(page).to have_content "You are not permitted to own own any more enterprises (limit is 1)."
expect(page).to have_content "#{enterprise_user.email} is not permitted to own any more enterprises (limit is 1)."
end
end
end
scenario "editing enterprises I have permission to" do
scenario "editing enterprises I manage" do
click_link 'Enterprises'
within('#listing_enterprises tbody tr:first') { click_link 'Edit Profile' }
within("#listing_enterprises tr.enterprise-#{distributor1.id}") { click_link 'Edit Profile' }
fill_in 'enterprise_name', :with => 'Eaterprises'
click_button 'Update'
flash_message.should == 'Enterprise "Eaterprises" has been successfully updated!'
page.should have_field 'enterprise_name', :with => 'Eaterprises'
distributor1.reload.name.should == 'Eaterprises'
end
describe "enterprises I have edit permission for, but do not manage" do
it "allows me to edit them" do
click_link 'Enterprises'
within("#listing_enterprises tr.enterprise-#{distributor3.id}") { click_link 'Edit Profile' }
fill_in 'enterprise_name', :with => 'Eaterprises'
click_button 'Update'
flash_message.should == 'Enterprise "Eaterprises" has been successfully updated!'
distributor3.reload.name.should == 'Eaterprises'
end
it "does not show links to manage shipping methods, payment methods or enterprise fees" do
click_link 'Enterprises'
within("#listing_enterprises tr.enterprise-#{distributor3.id}") do
page.should_not have_link 'Shipping Methods'
page.should_not have_link 'Payment Methods'
page.should_not have_link 'Enterprise Fees'
end
end
it "does not show links to manage shipping methods, payment methods or enterprise fees on the edit page", js: true do
click_link 'Enterprises'
within("#listing_enterprises tr.enterprise-#{distributor3.id}") { click_link 'Edit Profile' }
within(".side_menu") do
page.should_not have_link 'Shipping Methods'
page.should_not have_link 'Payment Methods'
page.should_not have_link 'Enterprise Fees'
end
end
end
scenario "editing images for an enterprise" do

View File

@@ -65,7 +65,7 @@ feature %q{
product = create(:product, supplier: supplier)
v1 = create(:variant, product: product)
v2 = create(:variant, product: product)
distributor = create(:distributor_enterprise, name: 'My distributor')
distributor = create(:distributor_enterprise, name: 'My distributor', with_payment_and_shipping: true)
# And some enterprise fees
supplier_fee = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee')
@@ -131,16 +131,16 @@ feature %q{
page.should have_selector 'td.distributors', text: 'My distributor'
# And it should have some fees
OrderCycle.last.exchanges.incoming.first.enterprise_fees.should == [supplier_fee]
OrderCycle.last.coordinator_fees.should == [coordinator_fee]
OrderCycle.last.exchanges.outgoing.first.enterprise_fees.should == [distributor_fee]
oc = OrderCycle.last
oc.exchanges.incoming.first.enterprise_fees.should == [supplier_fee]
oc.coordinator_fees.should == [coordinator_fee]
oc.exchanges.outgoing.first.enterprise_fees.should == [distributor_fee]
# And it should have some variants selected
OrderCycle.last.exchanges.first.variants.count.should == 2
OrderCycle.last.exchanges.last.variants.count.should == 2
oc.exchanges.first.variants.count.should == 2
oc.exchanges.last.variants.count.should == 2
# And my pickup time and instructions should have been saved
oc = OrderCycle.last
exchange = oc.exchanges.where(:sender_id => oc.coordinator_id).first
exchange.pickup_time.should == 'pickup time'
exchange.pickup_instructions.should == 'pickup instructions'
@@ -247,7 +247,7 @@ feature %q{
# And a coordinating, supplying and distributing enterprise with some products with variants
coordinator = create(:distributor_enterprise, name: 'My coordinator')
supplier = create(:supplier_enterprise, name: 'My supplier')
distributor = create(:distributor_enterprise, name: 'My distributor')
distributor = create(:distributor_enterprise, name: 'My distributor', with_payment_and_shipping: true)
product = create(:product, supplier: supplier)
v1 = create(:variant, product: product)
v2 = create(:variant, product: product)
@@ -360,9 +360,9 @@ feature %q{
scenario "updating many order cycle opening/closing times at once" do
# Given three order cycles
oc1 = create(:order_cycle)
oc2 = create(:order_cycle)
oc3 = create(:order_cycle)
oc1 = create(:simple_order_cycle)
oc2 = create(:simple_order_cycle)
oc3 = create(:simple_order_cycle)
# When I go to the order cycles page
login_to_admin_section
@@ -394,7 +394,7 @@ feature %q{
scenario "cloning an order cycle" do
# Given an order cycle
oc = create(:order_cycle)
oc = create(:simple_order_cycle)
# When I clone it
login_to_admin_section
@@ -434,6 +434,34 @@ feature %q{
end
describe "ensuring that hubs in order cycles have valid shipping and payment methods" do
context "when they don't" do
let(:hub) { create(:distributor_enterprise) }
let!(:oc) { create(:simple_order_cycle, distributors: [hub]) }
it "displays a warning on the dashboard" do
login_to_admin_section
page.should have_content "The hub #{hub.name} is listed in an active order cycle, but does not have valid shipping and payment methods. Until you set these up, customers will not be able to shop at this hub."
end
it "displays a warning on the order cycles screen" do
login_to_admin_section
visit admin_order_cycles_path
page.should have_content "The hub #{hub.name} is listed in an active order cycle, but does not have valid shipping and payment methods. Until you set these up, customers will not be able to shop at this hub."
end
end
context "when they do" do
let(:hub) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let!(:oc) { create(:simple_order_cycle, distributors: [hub]) }
it "does not display the warning on the dashboard" do
login_to_admin_section
page.should_not have_content "does not have valid shipping and payment methods"
end
end
end
context "as an enterprise user" do
let!(:supplier_managed) { create(:supplier_enterprise, name: 'Managed supplier') }
@@ -443,6 +471,9 @@ feature %q{
let!(:distributor_unmanaged) { create(:distributor_enterprise, name: 'Unmanaged Distributor') }
let!(:distributor_permitted) { create(:distributor_enterprise, name: 'Permitted distributor') }
let!(:distributor_managed_fee) { create(:enterprise_fee, enterprise: distributor_managed, name: 'Managed distributor fee') }
let!(:shipping_method) { create(:shipping_method, distributors: [distributor_managed, distributor_unmanaged, distributor_permitted]) }
let!(:payment_method) { create(:payment_method, distributors: [distributor_managed, distributor_unmanaged, distributor_permitted]) }
let!(:supplier_permitted_relationship) do
create(:enterprise_relationship, parent: supplier_permitted, child: supplier_managed,
permissions_list: [:add_to_order_cycle])
@@ -471,6 +502,10 @@ feature %q{
# I should see only the order cycle I am coordinating
page.should have_content oc_user_coordinating.name
page.should_not have_content oc_for_other_user.name
# The order cycle should show enterprises that I manage
page.should have_selector 'td.suppliers', text: supplier_managed.name
page.should have_selector 'td.distributors', text: distributor_managed.name
# The order cycle should not show enterprises that I don't manage
page.should_not have_selector 'td.suppliers', text: supplier_unmanaged.name
@@ -572,7 +607,163 @@ feature %q{
occ = OrderCycle.last
occ.name.should == "COPY OF #{oc.name}"
end
end
describe "simplified interface for enterprise users selling only their own produce" do
let(:user) { create_enterprise_user }
let(:enterprise) { create(:enterprise, is_primary_producer: true, sells: 'own') }
let!(:p1) { create(:simple_product, supplier: enterprise) }
let!(:p2) { create(:simple_product, supplier: enterprise) }
let!(:p3) { create(:simple_product, supplier: enterprise) }
let!(:v) { create(:variant, product: p3) }
let!(:fee) { create(:enterprise_fee, enterprise: enterprise, name: 'Coord fee') }
before do
user.enterprise_roles.create! enterprise: enterprise
login_to_admin_as user
end
it "shows me an index of order cycles without enterprise columns" do
create(:simple_order_cycle, coordinator: enterprise)
visit admin_order_cycles_path
page.should_not have_selector 'th', text: 'SUPPLIERS'
page.should_not have_selector 'th', text: 'COORDINATOR'
page.should_not have_selector 'th', text: 'DISTRIBUTORS'
end
it "creates order cycles", js: true do
# When I go to the new order cycle page
visit admin_order_cycles_path
click_link 'New Order Cycle'
# And I fill in the basic fields
fill_in 'order_cycle_name', with: 'Plums & Avos'
fill_in 'order_cycle_orders_open_at', with: '2014-10-17 06:00:00'
fill_in 'order_cycle_orders_close_at', with: '2014-10-24 17:00:00'
fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'pickup time'
fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions'
# Then my products / variants should already be selected
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{p1.master.id}"
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{p2.master.id}"
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{v.id}"
# When I unselect a product
uncheck "order_cycle_incoming_exchange_0_variants_#{p2.master.id}"
# And I add a fee and save
click_button 'Add coordinator fee'
click_button 'Add coordinator fee'
click_link 'order_cycle_coordinator_fee_1_remove'
page.should have_select 'order_cycle_coordinator_fee_0_id'
page.should_not have_select 'order_cycle_coordinator_fee_1_id'
select 'Coord fee', from: 'order_cycle_coordinator_fee_0_id'
click_button 'Create'
# Then my order cycle should have been created
page.should have_content 'Your order cycle has been created.'
page.should have_selector 'a', text: 'Plums & Avos'
page.should have_selector "input[value='2014-10-17 06:00:00 +1100']"
page.should have_selector "input[value='2014-10-24 17:00:00 +1100']"
# And it should have some variants selected
oc = OrderCycle.last
oc.exchanges.incoming.first.variants.count.should == 2
oc.exchanges.outgoing.first.variants.count.should == 2
# And it should have the fee
oc.coordinator_fees.should == [fee]
# And my pickup time and instructions should have been saved
ex = oc.exchanges.outgoing.first
ex.pickup_time.should == 'pickup time'
ex.pickup_instructions.should == 'pickup instructions'
end
scenario "editing an order cycle" do
# Given an order cycle with pickup time and instructions
fee = create(:enterprise_fee, name: 'my fee', enterprise: enterprise)
oc = create(:simple_order_cycle, suppliers: [enterprise], coordinator: enterprise, distributors: [enterprise], variants: [p1.master], coordinator_fees: [fee])
ex = oc.exchanges.outgoing.first
ex.update_attributes! pickup_time: 'pickup time', pickup_instructions: 'pickup instructions'
# When I edit it
login_to_admin_section
click_link 'Order Cycles'
click_link oc.name
wait_until { page.find('#order_cycle_name').value.present? }
# Then I should see the basic settings
page.should have_field 'order_cycle_name', with: oc.name
page.should have_field 'order_cycle_orders_open_at', with: oc.orders_open_at.to_s
page.should have_field 'order_cycle_orders_close_at', with: oc.orders_close_at.to_s
page.should have_field 'order_cycle_outgoing_exchange_0_pickup_time', with: 'pickup time'
page.should have_field 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions'
# And I should see the products
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{p1.master.id}"
page.should have_unchecked_field "order_cycle_incoming_exchange_0_variants_#{p2.master.id}"
page.should have_unchecked_field "order_cycle_incoming_exchange_0_variants_#{v.id}"
# And I should see the coordinator fees
page.should have_select 'order_cycle_coordinator_fee_0_id', selected: 'my fee'
end
scenario "updating an order cycle" do
# Given an order cycle with pickup time and instructions
fee1 = create(:enterprise_fee, name: 'my fee', enterprise: enterprise)
fee2 = create(:enterprise_fee, name: 'that fee', enterprise: enterprise)
oc = create(:simple_order_cycle, suppliers: [enterprise], coordinator: enterprise, distributors: [enterprise], variants: [p1.master], coordinator_fees: [fee1])
ex = oc.exchanges.outgoing.first
ex.update_attributes! pickup_time: 'pickup time', pickup_instructions: 'pickup instructions'
# When I edit it
login_to_admin_section
visit edit_admin_order_cycle_path oc
wait_until { page.find('#order_cycle_name').value.present? }
# And I fill in the basic fields
fill_in 'order_cycle_name', with: 'Plums & Avos'
fill_in 'order_cycle_orders_open_at', with: '2014-10-17 06:00:00'
fill_in 'order_cycle_orders_close_at', with: '2014-10-24 17:00:00'
fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'xy'
fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'zzy'
# And I make some product selections
uncheck "order_cycle_incoming_exchange_0_variants_#{p1.master.id}"
check "order_cycle_incoming_exchange_0_variants_#{p2.master.id}"
check "order_cycle_incoming_exchange_0_variants_#{v.id}"
uncheck "order_cycle_incoming_exchange_0_variants_#{v.id}"
# And I select some fees and update
click_link 'order_cycle_coordinator_fee_0_remove'
page.should_not have_select 'order_cycle_coordinator_fee_0_id'
click_button 'Add coordinator fee'
select 'that fee', from: 'order_cycle_coordinator_fee_0_id'
click_button 'Update'
# Then my order cycle should have been updated
page.should have_content 'Your order cycle has been updated.'
page.should have_selector 'a', text: 'Plums & Avos'
page.should have_selector "input[value='2014-10-17 06:00:00 +1100']"
page.should have_selector "input[value='2014-10-24 17:00:00 +1100']"
# And it should have a variant selected
oc = OrderCycle.last
oc.exchanges.incoming.first.variants.should == [p2.master]
oc.exchanges.outgoing.first.variants.should == [p2.master]
# And it should have the fee
oc.coordinator_fees.should == [fee2]
# And my pickup time and instructions should have been saved
ex = oc.exchanges.outgoing.first
ex.pickup_time.should == 'xy'
ex.pickup_instructions.should == 'zzy'
end
end

View File

@@ -95,7 +95,7 @@ feature %q{
# click the 'capture' link for the order
page.find("[data-action=capture][href*=#{@order.number}]").click
flash_message.should == "Payment Updated"
page.should have_content "Payment Updated"
# check the order was captured
@order.reload

View File

@@ -35,6 +35,58 @@ feature %q{
@enterprise_user.enterprise_roles.build(enterprise: d1).save
end
it "displays a link to the map page" do
visit '/admin'
page.should have_selector ".dashboard_item h3", text: "Your profile live"
page.should have_selector ".dashboard_item .button.bottom", text: "SEE #{d1.name.upcase} LIVE"
end
context "when enterprise has not been confirmed" do
before do
d1.confirmed_at = nil
d1.save!
end
it "displays a message telling to user to confirm" do
visit '/admin'
page.should have_selector ".alert-box", text: "Please confirm the email address for #{d1.name}. We've sent an email to #{d1.email}."
end
end
context "when visibilty is set to false" do
before do
d1.visible = false
d1.save!
end
it "displays a message telling how to set visibility" do
visit '/admin'
page.should have_selector ".alert-box", text: "To allow people to find you, turn on your visibility under Manage #{d1.name}."
end
end
pending "when user is a profile only" do
before do
d1.sells = "none"
d1.save!
end
it "does not show a products item" do
visit '/admin'
page.should_not have_selector "#products"
end
end
end
context "with multiple enterprises" do
let(:d1) { create(:distributor_enterprise) }
let(:d2) { create(:distributor_enterprise) }
before :each do
@enterprise_user.enterprise_roles.build(enterprise: d1).save
@enterprise_user.enterprise_roles.build(enterprise: d2).save
end
it "displays information about the enterprise" do
visit '/admin'
page.should have_selector ".dashboard_item#enterprises h3", text: "My Enterprises"

View File

@@ -6,6 +6,8 @@ feature %q{
} do
include AuthenticationWorkflow
include WebHelper
let!(:taxon) { create(:taxon) }
background do
@@ -15,7 +17,10 @@ feature %q{
end
describe "creating a product" do
scenario "assigning a important attributes", js: true do
let!(:tax_category) { create(:tax_category, name: 'Test Tax Category') }
let!(:shipping_category) { create(:shipping_category, name: 'Test Shipping Category') }
scenario "assigning important attributes", js: true do
login_to_admin_section
click_link 'Products'
@@ -28,6 +33,8 @@ feature %q{
select taxon.name, from: "product_primary_taxon_id"
fill_in 'product_price', with: '19.99'
fill_in 'product_on_hand', with: 5
select 'Test Tax Category', from: 'product_tax_category_id'
select 'Test Shipping Category', from: 'product_shipping_category_id'
fill_in 'product_description', with: "A description..."
click_button 'Create'
@@ -43,6 +50,8 @@ feature %q{
product.primary_taxon_id.should == taxon.id
product.price.to_s.should == '19.99'
product.on_hand.should == 5
product.tax_category_id.should == tax_category.id
product.shipping_category.should == shipping_category
product.description.should == "A description..."
product.group_buy.should be_false
product.master.option_values.map(&:name).should == ['5kg']
@@ -85,6 +94,7 @@ feature %q{
end
context "as an enterprise user" do
let!(:tax_category) { create(:tax_category) }
before do
@new_user = create_enterprise_user
@@ -117,6 +127,7 @@ feature %q{
page.should have_selector('#product_supplier_id')
select 'Another Supplier', :from => 'product_supplier_id'
select taxon.name, from: "product_primary_taxon_id"
select tax_category.name, from: "product_tax_category_id"
# Should only have suppliers listed which the user can manage
page.should have_select 'product_supplier_id', with_options: [@supplier2.name, @supplier_permitted.name]
@@ -127,6 +138,7 @@ feature %q{
flash_message.should == 'Product "A new product !!!" has been successfully created!'
product = Spree::Product.find_by_name('A new product !!!')
product.supplier.should == @supplier2
product.tax_category.should == tax_category
end
scenario "editing a product" do
@@ -135,10 +147,12 @@ feature %q{
visit spree.edit_admin_product_path product
select 'Permitted Supplier', from: 'product_supplier_id'
select tax_category.name, from: 'product_tax_category_id'
click_button 'Update'
flash_message.should == 'Product "a product" has been successfully updated!'
product.reload
product.supplier.should == @supplier_permitted
product.tax_category.should == tax_category
end
scenario "editing product distributions" do

View File

@@ -14,17 +14,19 @@ feature %q{
create(:distributor_enterprise)
])
end
it "should not show the Sales Total report" do
it "does not show super admin only reports" do
login_to_admin_as user
click_link "Reports"
page.should_not have_content "Sales Total"
page.should_not have_content "Users & Enterprises"
end
end
context "As an admin user" do
it "shows the Sales Total report" do
it "shows the super admin only reports" do
login_to_admin_section
click_link "Reports"
page.should have_content "Sales Total"
page.should have_content "Users & Enterprises"
end
end
end
@@ -57,6 +59,22 @@ feature %q{
end
end
describe "Order cycle management report" do
before do
login_to_admin_section
click_link "Reports"
end
scenario "order payment method report" do
click_link "Order Cycle Management"
rows = find("table#listing_order_payment_methods").all("thead tr")
table = rows.map { |r| r.all("th").map { |c| c.text.strip } }
table.sort.should == [
["First Name", "Last Name", "Email", "Phone", "Hub", "Shipping Method", "Payment Method", "Amount"]
].sort
end
end
scenario "orders and distributors report" do
login_to_admin_section
click_link 'Reports'
@@ -157,10 +175,56 @@ feature %q{
table = rows.map { |r| r.all("th,td").map { |c| c.text.strip } }
table.sort.should == [
["Supplier", "Producer Suburb", "Product", "Product Properties", "Variant Value", "Price", "Group Buy Unit Quantity", "Amount"],
[product_1.supplier.name, product_1.supplier.address.city, "Product Name", product_1.properties.join(", "), "Test", "100.0", product_1.group_buy_unit_size.to_s, ""],
[product_1.supplier.name, product_1.supplier.address.city, "Product Name", product_1.properties.join(", "), "S", "80.0", product_1.group_buy_unit_size.to_s, ""],
[product_2.supplier.name, product_1.supplier.address.city, "Product 2", product_1.properties.join(", "), "", "99.0", product_1.group_buy_unit_size.to_s, ""]
["Supplier", "Producer Suburb", "Product", "Product Properties", "Taxons", "Variant Value", "Price", "Group Buy Unit Quantity", "Amount"],
[product_1.supplier.name, product_1.supplier.address.city, "Product Name", product_1.properties.join(", "), product_1.primary_taxon.name, "Test", "100.0", product_1.group_buy_unit_size.to_s, ""],
[product_1.supplier.name, product_1.supplier.address.city, "Product Name", product_1.properties.join(", "), product_1.primary_taxon.name, "S", "80.0", product_1.group_buy_unit_size.to_s, ""],
[product_2.supplier.name, product_1.supplier.address.city, "Product 2", product_1.properties.join(", "), product_2.primary_taxon.name, "", "99.0", product_1.group_buy_unit_size.to_s, ""]
].sort
end
end
describe "users and enterprises report" do
let!(:enterprise1) { create( :enterprise, owner: create_enterprise_user ) }
let!(:enterprise2) { create( :enterprise, owner: create_enterprise_user ) }
let!(:enterprise3) { create( :enterprise, owner: create_enterprise_user ) }
before do
enterprise3.enterprise_roles.build( user: enterprise1.owner ).save
login_to_admin_section
click_link 'Reports'
click_link 'Users & Enterprises'
end
it "shows users and enterprises report" do
rows = find("table#users_and_enterprises").all("tr")
table = rows.map { |r| r.all("th,td").map { |c| c.text.strip }[0..2] }
table.sort.should == [
[ "User", "Relationship", "Enterprise" ],
[ enterprise1.owner.email, "owns", enterprise1.name ],
[ enterprise1.owner.email, "manages", enterprise1.name ],
[ enterprise2.owner.email, "owns", enterprise2.name ],
[ enterprise2.owner.email, "manages", enterprise2.name ],
[ enterprise3.owner.email, "owns", enterprise3.name ],
[ enterprise3.owner.email, "manages", enterprise3.name ],
[ enterprise1.owner.email, "manages", enterprise3.name ]
].sort
end
it "filters the list" do
select enterprise3.name, from: "enterprise_id_in"
select enterprise1.owner.email, from: "user_id_in"
click_button "Search"
rows = find("table#users_and_enterprises").all("tr")
table = rows.map { |r| r.all("th,td").map { |c| c.text.strip }[0..2] }
table.sort.should == [
[ "User", "Relationship", "Enterprise" ],
[ enterprise1.owner.email, "manages", enterprise3.name ]
].sort
end
end

View File

@@ -0,0 +1,203 @@
require 'spec_helper'
feature %q{
As an Administrator
With products I can add to order cycles
I want to override the stock level and price of those products
Without affecting other hubs that share the same products
}, js: true do
include AuthenticationWorkflow
include WebHelper
let!(:hub) { create(:distributor_enterprise) }
let!(:hub2) { create(:distributor_enterprise) }
let!(:producer) { create(:supplier_enterprise) }
let!(:er1) { create(:enterprise_relationship, parent: hub, child: producer,
permissions_list: [:add_to_order_cycle]) }
context "as an enterprise user" do
let(:user) { create_enterprise_user enterprises: [hub2, producer] }
before { quick_login_as user }
describe "selecting a hub" do
it "displays a list of hub choices" do
visit '/admin/variant_overrides'
page.should have_select2 'hub_id', options: ['', hub.name, hub2.name]
end
it "displays the hub" do
visit '/admin/variant_overrides'
select2_select hub.name, from: 'hub_id'
click_button 'Go'
page.should have_selector 'h2', text: hub.name
end
end
context "when a hub is selected" do
let!(:product) { create(:simple_product, supplier: producer, variant_unit: 'weight', variant_unit_scale: 1) }
let!(:variant) { create(:variant, product: product, unit_value: 1, price: 1.23, on_hand: 12) }
let!(:producer_related) { create(:supplier_enterprise) }
let!(:product_related) { create(:simple_product, supplier: producer_related) }
let!(:variant_related) { create(:variant, product: product_related, unit_value: 2, price: 2.34, on_hand: 23) }
let!(:er2) { create(:enterprise_relationship, parent: producer_related, child: hub,
permissions_list: [:create_variant_overrides]) }
let!(:producer_unrelated) { create(:supplier_enterprise) }
let!(:product_unrelated) { create(:simple_product, supplier: producer_unrelated) }
before do
# Remove 'S' option value
variant.option_values.first.destroy
end
context "with no overrides" do
before do
visit '/admin/variant_overrides'
select2_select hub.name, from: 'hub_id'
click_button 'Go'
end
it "displays the list of products with variants" do
page.should have_table_row ['PRODUCER', 'PRODUCT', 'PRICE', 'ON HAND']
page.should have_table_row [producer.name, product.name, '', '']
page.should have_input "variant-overrides-#{variant.id}-price", placeholder: '1.23'
page.should have_input "variant-overrides-#{variant.id}-count-on-hand", placeholder: '12'
page.should have_table_row [producer_related.name, product_related.name, '', '']
page.should have_input "variant-overrides-#{variant_related.id}-price", placeholder: '2.34'
page.should have_input "variant-overrides-#{variant_related.id}-count-on-hand", placeholder: '23'
end
it "filters the products to those the hub can override" do
page.should_not have_content producer_unrelated.name
page.should_not have_content product_unrelated.name
end
it "creates new overrides" do
fill_in "variant-overrides-#{variant.id}-price", with: '777.77'
fill_in "variant-overrides-#{variant.id}-count-on-hand", with: '123'
page.should have_content "Changes to one override remain unsaved."
expect do
click_button 'Save Changes'
page.should have_content "Changes saved."
end.to change(VariantOverride, :count).by(1)
vo = VariantOverride.last
vo.variant_id.should == variant.id
vo.hub_id.should == hub.id
vo.price.should == 777.77
vo.count_on_hand.should == 123
end
describe "creating and then updating the new override" do
it "updates the same override instead of creating a duplicate" do
# When I create a new override
fill_in "variant-overrides-#{variant.id}-price", with: '777.77'
fill_in "variant-overrides-#{variant.id}-count-on-hand", with: '123'
page.should have_content "Changes to one override remain unsaved."
expect do
click_button 'Save Changes'
page.should have_content "Changes saved."
end.to change(VariantOverride, :count).by(1)
# And I update its settings without reloading the page
fill_in "variant-overrides-#{variant.id}-price", with: '111.11'
fill_in "variant-overrides-#{variant.id}-count-on-hand", with: '111'
page.should have_content "Changes to one override remain unsaved."
# Then I shouldn't see a new override
expect do
click_button 'Save Changes'
page.should have_content "Changes saved."
end.to change(VariantOverride, :count).by(0)
# And the override should be updated
vo = VariantOverride.last
vo.variant_id.should == variant.id
vo.hub_id.should == hub.id
vo.price.should == 111.11
vo.count_on_hand.should == 111
end
end
it "displays an error when unauthorised to access the page" do
fill_in "variant-overrides-#{variant.id}-price", with: '777.77'
fill_in "variant-overrides-#{variant.id}-count-on-hand", with: '123'
page.should have_content "Changes to one override remain unsaved."
user.enterprises.clear
expect do
click_button 'Save Changes'
page.should have_content "I couldn't get authorisation to save those changes, so they remain unsaved."
end.to change(VariantOverride, :count).by(0)
end
it "displays an error when unauthorised to update a particular override" do
fill_in "variant-overrides-#{variant_related.id}-price", with: '777.77'
fill_in "variant-overrides-#{variant_related.id}-count-on-hand", with: '123'
page.should have_content "Changes to one override remain unsaved."
er2.destroy
expect do
click_button 'Save Changes'
page.should have_content "I couldn't get authorisation to save those changes, so they remain unsaved."
end.to change(VariantOverride, :count).by(0)
end
end
context "with overrides" do
let!(:vo) { create(:variant_override, variant: variant, hub: hub, price: 77.77, count_on_hand: 11111) }
before do
visit '/admin/variant_overrides'
select2_select hub.name, from: 'hub_id'
click_button 'Go'
end
it "product values are affected by overrides" do
page.should have_input "variant-overrides-#{variant.id}-price", with: '77.77', placeholder: '1.23'
page.should have_input "variant-overrides-#{variant.id}-count-on-hand", with: '11111', placeholder: '12'
end
it "updates existing overrides" do
fill_in "variant-overrides-#{variant.id}-price", with: '22.22'
fill_in "variant-overrides-#{variant.id}-count-on-hand", with: '8888'
page.should have_content "Changes to one override remain unsaved."
expect do
click_button 'Save Changes'
page.should have_content "Changes saved."
end.to change(VariantOverride, :count).by(0)
vo.reload
vo.variant_id.should == variant.id
vo.hub_id.should == hub.id
vo.price.should == 22.22
vo.count_on_hand.should == 8888
end
it "deletes overrides when values are cleared" do
fill_in "variant-overrides-#{variant.id}-price", with: ''
fill_in "variant-overrides-#{variant.id}-count-on-hand", with: ''
page.should have_content "Changes to one override remain unsaved."
expect do
click_button 'Save Changes'
page.should have_content "Changes saved."
end.to change(VariantOverride, :count).by(-1)
VariantOverride.where(id: vo.id).should be_empty
end
end
end
end
end

View File

@@ -14,9 +14,6 @@ feature 'Groups', js: true do
it "renders enterprise modals for groups" do
visit groups_path
page.should have_content enterprise.name
open_enterprise_modal enterprise
modal_should_be_open_for enterprise
page.should have_content "Herndon, Vic"
page.should have_content group.name
end
end

View File

@@ -4,22 +4,22 @@ feature 'Home', js: true do
include AuthenticationWorkflow
include UIComponentHelper
let!(:distributor) { create(:distributor_enterprise) }
let!(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let!(:invisible_distributor) { create(:distributor_enterprise, visible: false) }
let(:d1) { create(:distributor_enterprise) }
let(:d2) { create(:distributor_enterprise) }
let!(:order_cycle) { create(:order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) }
let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) }
let!(:producer) { create(:supplier_enterprise) }
let!(:er) { create(:enterprise_relationship, parent: distributor, child: producer) }
before do
visit "/"
visit "/"
end
it "shows hubs" do
page.should have_content distributor.name
expand_active_table_node distributor.name
page.should have_content "OUR PRODUCERS"
page.should have_content "OUR PRODUCERS"
end
it "does not show invisible hubs" do
@@ -35,7 +35,7 @@ feature 'Home', js: true do
it "should link to the hub page" do
follow_active_table_node distributor.name
current_path.should == "/shop"
current_path.should == enterprise_shop_path(distributor)
end
it "should show hub producer modals" do

View File

@@ -51,7 +51,7 @@ feature "Registration", js: true do
expect(page).to have_content 'Nice one!'
e = Enterprise.find_by_name('My Awesome Enterprise')
expect(e.address.address1).to eq "123 Abc Street"
expect(e.sells).to eq "none"
expect(e.sells).to eq "unspecified"
expect(e.is_primary_producer).to eq true
expect(e.contact).to eq "Saskia Munroe"

View File

@@ -7,7 +7,7 @@ feature "As a consumer I want to check out my cart", js: true do
include CheckoutWorkflow
include UIComponentHelper
let(:distributor) { create(:distributor_enterprise) }
let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let(:supplier) { create(:supplier_enterprise) }
let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) }
let(:product) { create(:simple_product, supplier: supplier) }

View File

@@ -27,9 +27,19 @@ feature "As a consumer I want to check out my cart", js: true do
page.should have_content distributor.name
end
describe "with shipping methods" do
describe "with shipping and payment methods" do
let(:sm1) { create(:shipping_method, require_ship_address: true, name: "Frogs", description: "yellow", calculator: Spree::Calculator::FlatRate.new(preferred_amount: 0.00)) }
let(:sm2) { create(:shipping_method, require_ship_address: false, name: "Donkeys", description: "blue", calculator: Spree::Calculator::FlatRate.new(preferred_amount: 4.56)) }
let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::PaymentMethod::Check") }
let!(:pm2) { create(:payment_method, distributors: [distributor]) }
let!(:pm3) do
Spree::Gateway::PayPalExpress.create!(name: "Paypal", environment: 'test', distributor_ids: [distributor.id]).tap do |pm|
pm.preferred_login = 'devnull-facilitator_api1.rohanmitchell.com'
pm.preferred_password = '1406163716'
pm.preferred_signature = 'AFcWxV21C7fd0v3bYYYRCpSSRl31AaTntNJ-AjvUJkWf4dgJIvcLsf1V'
end
end
before do
distributor.shipping_methods << sm1
distributor.shipping_methods << sm2
@@ -68,32 +78,65 @@ feature "As a consumer I want to check out my cart", js: true do
end
end
describe "with payment methods" do
let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::PaymentMethod::Check") }
let!(:pm2) { create(:payment_method, distributors: [distributor]) }
let!(:pm3) do
Spree::Gateway::PayPalExpress.create!(name: "Paypal", environment: 'test', distributor_ids: [distributor.id]).tap do |pm|
pm.preferred_login = 'devnull-facilitator_api1.rohanmitchell.com'
pm.preferred_password = '1406163716'
pm.preferred_signature = 'AFcWxV21C7fd0v3bYYYRCpSSRl31AaTntNJ-AjvUJkWf4dgJIvcLsf1V'
end
context "on the checkout page with payments open" do
before do
ActionMailer::Base.deliveries.clear
visit checkout_path
checkout_as_guest
toggle_payment
end
context "on the checkout page with payments open" do
before do
visit checkout_path
checkout_as_guest
it "shows all available payment methods" do
page.should have_content pm1.name
page.should have_content pm2.name
page.should have_content pm3.name
end
describe "purchasing" do
it "takes us to the order confirmation page when we submit a complete form" do
toggle_details
within "#details" do
fill_in "First Name", with: "Will"
fill_in "Last Name", with: "Marshall"
fill_in "Email", with: "test@test.com"
fill_in "Phone", with: "0468363090"
end
toggle_billing
within "#billing" do
fill_in "Address", with: "123 Your Face"
select "Australia", from: "Country"
select "Victoria", from: "State"
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
end
toggle_shipping
within "#shipping" do
choose sm2.name
fill_in 'Any notes or custom delivery instructions?', with: "SpEcIaL NoTeS"
end
toggle_payment
within "#payment" do
choose pm1.name
end
ActionMailer::Base.deliveries.length.should == 0
place_order
page.should have_content "Your order has been processed successfully"
ActionMailer::Base.deliveries.length.should == 2
email = ActionMailer::Base.deliveries.last
site_name = Spree::Config[:site_name]
email.subject.should include "#{site_name} Order Confirmation"
o = Spree::Order.complete.first
expect(o.special_instructions).to eq "SpEcIaL NoTeS"
end
it "shows all available payment methods" do
page.should have_content pm1.name
page.should have_content pm2.name
page.should have_content pm3.name
end
describe "purchasing" do
it "takes us to the order confirmation page when we submit a complete form" do
context "with basic details filled" do
before do
toggle_shipping
choose sm1.name
toggle_payment
choose pm1.name
toggle_details
within "#details" do
fill_in "First Name", with: "Will"
@@ -103,135 +146,95 @@ feature "As a consumer I want to check out my cart", js: true do
end
toggle_billing
within "#billing" do
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
fill_in "Address", with: "123 Your Face"
select "Australia", from: "Country"
select "Victoria", from: "State"
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
end
toggle_shipping
within "#shipping" do
choose sm2.name
fill_in 'Any notes or custom delivery instructions?', with: "SpEcIaL NoTeS"
end
toggle_payment
within "#payment" do
choose pm1.name
end
place_order
page.should have_content "Your order has been processed successfully"
ActionMailer::Base.deliveries.length.should == 2
email = ActionMailer::Base.deliveries.last
site_name = Spree::Config[:site_name]
email.subject.should include "#{site_name} Order Confirmation"
o = Spree::Order.complete.first
expect(o.special_instructions).to eq "SpEcIaL NoTeS"
check "Shipping address same as billing address?"
end
context "with basic details filled" do
before do
toggle_shipping
choose sm1.name
toggle_payment
choose pm1.name
toggle_details
within "#details" do
fill_in "First Name", with: "Will"
fill_in "Last Name", with: "Marshall"
fill_in "Email", with: "test@test.com"
fill_in "Phone", with: "0468363090"
end
toggle_billing
within "#billing" do
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
fill_in "Address", with: "123 Your Face"
select "Australia", from: "Country"
select "Victoria", from: "State"
end
toggle_shipping
check "Shipping address same as billing address?"
end
it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do
place_order
page.should have_content "Your order has been processed successfully"
end
it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do
context "when we are charged a shipping fee" do
before { choose sm2.name }
it "creates a payment for the full amount inclusive of shipping" do
place_order
page.should have_content "Your order has been processed successfully"
# There are two orders - our order and our new cart
o = Spree::Order.complete.first
o.adjustments.shipping.first.amount.should == 4.56
o.payments.first.amount.should == 10 + 1.23 + 4.56 # items + fees + shipping
end
end
context "with a credit card payment method" do
let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::Gateway::Bogus") }
it "takes us to the order confirmation page when submitted with a valid credit card" do
toggle_payment
fill_in 'Card Number', with: "4111111111111111"
select 'February', from: 'secrets.card_month'
select (Date.today.year+1).to_s, from: 'secrets.card_year'
fill_in 'Security Code', with: '123'
place_order
page.should have_content "Your order has been processed successfully"
# Order should have a payment with the correct amount
o = Spree::Order.complete.first
o.payments.first.amount.should == 11.23
end
context "when we are charged a shipping fee" do
before { choose sm2.name }
it "shows the payment processing failed message when submitted with an invalid credit card" do
toggle_payment
fill_in 'Card Number', with: "9999999988887777"
select 'February', from: 'secrets.card_month'
select (Date.today.year+1).to_s, from: 'secrets.card_year'
fill_in 'Security Code', with: '123'
it "creates a payment for the full amount inclusive of shipping" do
place_order
page.should have_content "Your order has been processed successfully"
place_order
page.should have_content "Payment could not be processed, please check the details you entered"
# There are two orders - our order and our new cart
o = Spree::Order.complete.first
o.adjustments.shipping.first.amount.should == 4.56
o.payments.first.amount.should == 10 + 1.23 + 4.56 # items + fees + shipping
end
end
context "with a credit card payment method" do
let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::Gateway::Bogus") }
it "takes us to the order confirmation page when submitted with a valid credit card" do
toggle_payment
fill_in 'Card Number', with: "4111111111111111"
select 'February', from: 'secrets.card_month'
select (Date.today.year+1).to_s, from: 'secrets.card_year'
fill_in 'Security Code', with: '123'
place_order
page.should have_content "Your order has been processed successfully"
# Order should have a payment with the correct amount
o = Spree::Order.complete.first
o.payments.first.amount.should == 11.23
end
it "shows the payment processing failed message when submitted with an invalid credit card" do
toggle_payment
fill_in 'Card Number', with: "9999999988887777"
select 'February', from: 'secrets.card_month'
select (Date.today.year+1).to_s, from: 'secrets.card_year'
fill_in 'Security Code', with: '123'
place_order
page.should have_content "Payment could not be processed, please check the details you entered"
# Does not show duplicate shipping fee
visit checkout_path
page.all("th", text: "Shipping").count.should == 1
end
# Does not show duplicate shipping fee
visit checkout_path
page.all("th", text: "Shipping").count.should == 1
end
end
end
end
end
context "when the customer has a pre-set shipping and billing address" do
before do
# Load up the customer's order and give them a shipping and billing address
# This is equivalent to when the customer has ordered before and their addresses
# are pre-populated.
o = Spree::Order.last
o.ship_address = build(:address)
o.bill_address = build(:address)
o.save!
end
context "when the customer has a pre-set shipping and billing address" do
before do
ActionMailer::Base.deliveries.clear
# Load up the customer's order and give them a shipping and billing address
# This is equivalent to when the customer has ordered before and their addresses
# are pre-populated.
o = Spree::Order.last
o.ship_address = build(:address)
o.bill_address = build(:address)
o.save!
end
it "checks out successfully" do
visit checkout_path
checkout_as_guest
choose sm2.name
toggle_payment
choose pm1.name
it "checks out successfully" do
visit checkout_path
checkout_as_guest
choose sm2.name
toggle_payment
choose pm1.name
place_order
page.should have_content "Your order has been processed successfully"
ActionMailer::Base.deliveries.length.should == 2
end
expect(ActionMailer::Base.deliveries.length).to be 0
place_order
page.should have_content "Your order has been processed successfully"
expect(ActionMailer::Base.deliveries.length).to be 2
end
end
end

View File

@@ -8,7 +8,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
describe "Viewing a distributor" do
let(:distributor) { create(:distributor_enterprise) }
let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let(:supplier) { create(:supplier_enterprise) }
let(:oc1) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 2.days.from_now) }
let(:oc2) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 3.days.from_now) }
@@ -76,7 +76,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
page.should have_content "Next order closing in 2 days"
Spree::Order.last.order_cycle.should == oc1
page.should have_content product.name
page.should have_content product.master.display_name.capitalize
page.should have_content product.master.display_name
page.should have_content product.master.display_as
open_product_modal product
@@ -119,7 +119,6 @@ feature "As a consumer I want to shop with a distributor", js: true do
page.should have_price "$53.00"
# Product price should be listed as the lesser of these
#page.should have_selector 'tr.product > td', text: "from $43.00"
page.should have_price "$43.00"
end
end
@@ -171,11 +170,10 @@ feature "As a consumer I want to shop with a distributor", js: true do
fill_in "variants[#{variant.id}]", with: 6
fill_in "variant_attributes[#{variant.id}][max_quantity]", with: 7
page.should have_in_cart product.name
wait_until { !cart_dirty }
li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last
while li == nil
sleep 0.1
li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last
end
li.max_quantity.should == 7
li.quantity.should == 6
end

View File

@@ -0,0 +1,196 @@
require 'spec_helper'
feature "shopping with variant overrides defined", js: true do
include AuthenticationWorkflow
include WebHelper
include ShopWorkflow
include CheckoutWorkflow
include UIComponentHelper
let(:hub) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let(:producer) { create(:supplier_enterprise) }
let(:oc) { create(:simple_order_cycle, suppliers: [producer], coordinator: hub, distributors: [hub]) }
let(:outgoing_exchange) { oc.exchanges.outgoing.first }
let(:sm) { hub.shipping_methods.first }
let(:pm) { hub.payment_methods.first }
let(:p1) { create(:simple_product, supplier: producer) }
let(:p2) { create(:simple_product, supplier: producer) }
let(:v1) { create(:variant, product: p1, price: 11.11, unit_value: 1) }
let(:v2) { create(:variant, product: p1, price: 22.22, unit_value: 2) }
let(:v3) { create(:variant, product: p2, price: 33.33, unit_value: 3) }
let(:v4) { create(:variant, product: p1, price: 44.44, unit_value: 4) }
let!(:vo1) { create(:variant_override, hub: hub, variant: v1, price: 55.55, count_on_hand: nil) }
let!(:vo2) { create(:variant_override, hub: hub, variant: v2, count_on_hand: 0) }
let!(:vo3) { create(:variant_override, hub: hub, variant: v3, count_on_hand: 0) }
let!(:vo4) { create(:variant_override, hub: hub, variant: v4, count_on_hand: 3) }
let(:ef) { create(:enterprise_fee, enterprise: hub, fee_type: 'packing', calculator: Spree::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 10)) }
before do
ActionMailer::Base.deliveries.clear
outgoing_exchange.variants = [v1, v2, v3, v4]
outgoing_exchange.enterprise_fees << ef
visit shop_path
click_link hub.name
end
describe "viewing products" do
it "shows the overridden price" do
page.should_not have_price "$12.22" # $11.11 + 10% fee
page.should have_price "$61.11"
end
it "looks up stock from the override" do
# Product should appear but one of the variants is out of stock
page.should_not have_content v2.options_text
# Entire product should not appear - no stock
page.should_not have_content p2.name
page.should_not have_content v3.options_text
end
it "calculates fees correctly" do
page.find("#variant-#{v1.id} .graph-button").click
page.find(".price_breakdown a").click
page.should have_selector 'li.cost div', text: '$55.55'
page.should have_selector 'li.packing-fee div', text: '$5.56'
page.should have_selector 'li.total div', text: '= $61.11'
end
it "shows the correct prices when products are in the cart" do
fill_in "variants[#{v1.id}]", with: "2"
show_cart
wait_until_enabled 'li.cart a.button'
visit shop_path
page.should_not have_price '$12.22'
end
# The two specs below reveal an unrelated issue with fee calculation. See:
# https://github.com/openfoodfoundation/openfoodnetwork/issues/312
it "shows the overridden price with fees in the quick cart" do
fill_in "variants[#{v1.id}]", with: "2"
show_cart
page.should have_selector "#cart-variant-#{v1.id} .quantity", text: '2'
page.should have_selector "#cart-variant-#{v1.id} .price", text: '$61.11'
page.should have_selector "#cart-variant-#{v1.id} .total-price", text: '$122.22'
end
it "shows the correct prices in the shopping cart" do
fill_in "variants[#{v1.id}]", with: "2"
add_to_cart
page.should have_selector "tr.line-item.variant-#{v1.id} .cart-item-price", text: '$61.11'
page.should have_field "order[line_items_attributes][0][quantity]", with: '2'
page.should have_selector "tr.line-item.variant-#{v1.id} .cart-item-total", text: '$122.22'
page.should have_selector "#edit-cart .item-total", text: '$122.21'
page.should have_selector "#edit-cart .grand-total", text: '$122.21'
end
it "shows the correct prices in the checkout" do
fill_in "variants[#{v1.id}]", with: "2"
show_cart
wait_until_enabled 'li.cart a.button'
click_link 'Checkout now'
page.should have_selector 'form.edit_order .cart-total', text: '$122.21'
page.should have_selector 'form.edit_order .shipping', text: '$0.00'
page.should have_selector 'form.edit_order .total', text: '$122.21'
end
end
describe "creating orders" do
it "creates the order with the correct prices" do
fill_in "variants[#{v1.id}]", with: "2"
show_cart
wait_until_enabled 'li.cart a.button'
click_link 'Checkout now'
complete_checkout
ActionMailer::Base.deliveries.length.should == 2
email = ActionMailer::Base.deliveries.last
o = Spree::Order.complete.last
o.line_items.first.price.should == 55.55
o.total.should == 122.21
email.body.should include "$122.21"
end
it "subtracts stock from the override" do
fill_in "variants[#{v4.id}]", with: "2"
show_cart
wait_until_enabled 'li.cart a.button'
click_link 'Checkout now'
expect do
expect do
complete_checkout
end.to change { v4.reload.count_on_hand }.by(0)
end.to change { vo4.reload.count_on_hand }.by(-2)
end
it "does not subtract stock from overrides that do not override count_on_hand" do
fill_in "variants[#{v1.id}]", with: "2"
show_cart
wait_until_enabled 'li.cart a.button'
click_link 'Checkout now'
expect do
complete_checkout
end.to change { v1.reload.count_on_hand }.by(-2)
vo1.reload.count_on_hand.should be_nil
end
it "does not show out of stock flags on order confirmation page" do
v4.update_attribute :count_on_hand, 0
fill_in "variants[#{v4.id}]", with: "2"
show_cart
wait_until_enabled 'li.cart a.button'
click_link 'Checkout now'
complete_checkout
page.should_not have_content "Out of Stock"
end
end
private
def complete_checkout
checkout_as_guest
within "#details" do
fill_in "First Name", with: "Some"
fill_in "Last Name", with: "One"
fill_in "Email", with: "test@example.com"
fill_in "Phone", with: "0456789012"
end
toggle_billing
within "#billing" do
fill_in "Address", with: "123 Street"
select "Australia", from: "Country"
select "Victoria", from: "State"
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
end
toggle_shipping
within "#shipping" do
choose sm.name
end
toggle_payment
within "#payment" do
choose pm.name
end
place_order
page.should have_content "Your order has been processed successfully"
end
end

View File

@@ -15,8 +15,8 @@ feature %q{
scenario "entering the site via a supplier's page" do
# Given a supplier with some distributed products
s = create(:supplier_enterprise)
d = create(:distributor_enterprise)
p = create(:simple_product, supplier: s) #, distributors: [d])
d = create(:distributor_enterprise, with_payment_and_shipping: true)
p = create(:simple_product, supplier: s)
oc = create(:simple_order_cycle, suppliers: [s], distributors: [d], variants: [p.master])
# When I visit a supplier page

View File

@@ -4,11 +4,12 @@ require 'spec_helper'
describe CheckoutHelper do
it "generates html for validated inputs" do
helper.should_receive(:render).with(
partial: "shared/validated_input",
locals: {name: "test", path: "foo",
attributes: {:required=>true, :type=>:email, :name=>"foo", :id=>"foo", "ng-model"=>"foo", "ng-class"=>"{error: !fieldValid('foo')}"}}
"shared/validated_input",
name: "test",
path: "foo",
attributes: {:required=>true, :type=>:email, :name=>"foo", :id=>"foo", "ng-model"=>"foo", "ng-class"=>"{error: !fieldValid('foo')}"}
)
helper.validated_input("test", "foo", type: :email)
end
end

View File

@@ -1,15 +1,17 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the GroupsHelper. For example:
#
# describe GroupsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
describe GroupsHelper do
pending "add some examples to (or delete) #{__FILE__}"
describe "ext_url" do
it "adds prefix if missing" do
expect(helper.ext_url("http://example.com/", "http://example.com/bla")).to eq("http://example.com/bla")
expect(helper.ext_url("http://example.com/", "bla")).to eq("http://example.com/bla")
end
end
describe "strip_url" do
it "removes http(s)://" do
expect(helper.strip_url("http://example.com/")).to eq("example.com/")
expect(helper.strip_url("https://example.com/")).to eq("example.com/")
expect(helper.strip_url("example.com")).to eq("example.com")
end
end
end

View File

@@ -12,12 +12,17 @@ describe InjectionHelper do
helper.inject_enterprises.should match enterprise.facebook
end
it "only injects activated enterprises" do
inactive_enterprise = create(:enterprise, sells: 'unspecified')
helper.inject_enterprises.should_not match inactive_enterprise.name
end
it "injects shipping_methods" do
sm = create(:shipping_method)
helper.stub(:current_order).and_return order = create(:order)
helper.stub_chain(:current_distributor, :shipping_methods, :uniq).and_return [sm]
helper.inject_available_shipping_methods.should match sm.id.to_s
helper.inject_available_shipping_methods.should match sm.compute_amount(order).to_s
helper.inject_available_shipping_methods.should match sm.compute_amount(order).to_s
end
it "injects payment methods" do
@@ -28,7 +33,7 @@ describe InjectionHelper do
end
it "injects current order" do
helper.stub(:current_order).and_return order = create(:order)
helper.stub(:current_order).and_return order = create(:order)
helper.inject_current_order.should match order.id.to_s
end

View File

@@ -1,28 +1,36 @@
require 'spec_helper'
describe OrderCyclesHelper do
describe "generating local/remote classes for order cycle selection" do
it "returns blank when no distributor or order cycle is selected" do
helper.order_cycle_local_remote_class(nil, double(:order_cycle)).should == ''
helper.order_cycle_local_remote_class(double(:distributor), nil).should == ''
describe "finding hub enterprises" do
let(:e) { create(:distributor_enterprise, name: 'enterprise') }
before do
helper.stub(:order_cycle_permitted_enterprises) { Enterprise.where(id: e.id) }
end
it "returns local when the order cycle includes the current distributor" do
distributor = double(:enterprise)
order_cycle = double(:order_cycle, distributors: [distributor])
helper.order_cycle_local_remote_class(distributor, order_cycle).should == ' local'
it "returns enterprises without shipping methods as disabled" do
create(:payment_method, distributors: [e])
helper.order_cycle_hub_enterprises.should == [['enterprise (no shipping methods)', e.id, {disabled: true}]]
end
it "returns remote when the order cycle does not include the current distributor" do
distributor = double(:enterprise)
order_cycle = double(:order_cycle, distributors: [])
it "returns enterprises without payment methods as disabled" do
create(:shipping_method, distributors: [e])
helper.order_cycle_hub_enterprises.should == [['enterprise (no payment methods)', e.id, {disabled: true}]]
end
helper.order_cycle_local_remote_class(distributor, order_cycle).should == ' remote'
it "returns enterprises with unavailable payment methods as disabled" do
create(:shipping_method, distributors: [e])
create(:payment_method, distributors: [e], active: false)
helper.order_cycle_hub_enterprises.should == [['enterprise (no payment methods)', e.id, {disabled: true}]]
end
it "returns enterprises with neither shipping nor payment methods as disabled" do
helper.order_cycle_hub_enterprises.should == [['enterprise (no shipping or payment methods)', e.id, {disabled: true}]]
end
end
it "gives me the pickup time for an order_cycle" do
describe "pickup time" do
it "gives me the pickup time for the current order cycle" do
d = create(:distributor_enterprise, name: 'Green Grass')
oc1 = create(:simple_order_cycle, name: 'oc 1', distributors: [d])
exchange = Exchange.find(oc1.exchanges.to_enterprises(d).outgoing.first.id)
@@ -31,9 +39,9 @@ describe OrderCyclesHelper do
helper.stub(:current_order_cycle).and_return oc1
helper.stub(:current_distributor).and_return d
helper.pickup_time.should == "turtles"
end
end
it "should give me the pickup time for any order cycle" do
it "gives me the pickup time for any order cycle" do
d = create(:distributor_enterprise, name: 'Green Grass')
oc1 = create(:simple_order_cycle, name: 'oc 1', distributors: [d])
oc2= create(:simple_order_cycle, name: 'oc 1', distributors: [d])
@@ -44,5 +52,6 @@ describe OrderCyclesHelper do
helper.stub(:current_order_cycle).and_return oc1
helper.stub(:current_distributor).and_return d
helper.pickup_time(oc2).should == "turtles"
end
end
end

View File

@@ -0,0 +1,57 @@
describe "VariantOverridesCtrl", ->
ctrl = null
scope = null
hubs = [{id: 1, name: 'Hub'}]
producers = [{id: 2, name: 'Producer'}]
products = [{id: 1, name: 'Product'}]
hubPermissions = {}
VariantOverrides = null
variantOverrides = {}
beforeEach ->
module 'ofn.admin'
module ($provide) ->
$provide.value 'SpreeApiKey', 'API_KEY'
$provide.value 'variantOverrides', variantOverrides
null
scope = {}
inject ($controller, Indexer, _VariantOverrides_) ->
VariantOverrides = _VariantOverrides_
ctrl = $controller 'AdminVariantOverridesCtrl', {$scope: scope, Indexer: Indexer, hubs: hubs, producers: producers, products: products, hubPermissions: hubPermissions, VariantOverrides: _VariantOverrides_}
it "initialises the hub list and the chosen hub", ->
expect(scope.hubs).toEqual hubs
expect(scope.hub).toBeNull()
it "adds products", ->
spyOn(VariantOverrides, "ensureDataFor")
expect(scope.products).toEqual []
scope.addProducts ['a', 'b']
expect(scope.products).toEqual ['a', 'b']
scope.addProducts ['c', 'd']
expect(scope.products).toEqual ['a', 'b', 'c', 'd']
expect(VariantOverrides.ensureDataFor).toHaveBeenCalled()
describe "selecting a hub", ->
it "sets the chosen hub", ->
scope.hub_id = 1
scope.selectHub()
expect(scope.hub).toEqual hubs[0]
it "does nothing when no selection has been made", ->
scope.hub_id = ''
scope.selectHub
expect(scope.hub).toBeNull
describe "updating", ->
describe "error messages", ->
it "returns an unauthorised message upon 401", ->
expect(scope.updateError({}, 401)).toEqual "I couldn't get authorisation to save those changes, so they remain unsaved."
it "returns errors when they are provided", ->
data = {errors: {base: ["Hub can't be blank", "Variant can't be blank"]}}
expect(scope.updateError(data, 400)).toEqual "I had some trouble saving: Hub can't be blank, Variant can't be blank"
it "returns a generic message otherwise", ->
expect(scope.updateError({}, 500)).toEqual "Oh no! I was unable to save your changes."

View File

@@ -4,25 +4,21 @@ describe "enterpriseCtrl", ->
Enterprise = null
PaymentMethods = null
ShippingMethods = null
longDescriptionMock = ["long description text"]
beforeEach ->
module('admin.enterprises')
module ($provide)->
$provide.value "longDescription", longDescriptionMock
null
Enterprise =
enterprise:
payment_method_ids: [ 1, 3 ]
shipping_method_ids: [ 2, 4 ]
is_primary_producer: true
sells: "none"
PaymentMethods =
paymentMethods: [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 } ]
paymentMethods: "payment methods"
ShippingMethods =
shippingMethods: [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 } ]
shippingMethods: "shipping methods"
inject ($controller) ->
scope = {}
ctrl = $controller 'enterpriseCtrl', {$scope: scope, Enterprise: Enterprise, PaymentMethods: PaymentMethods, ShippingMethods: ShippingMethods}
inject ($rootScope, $controller) ->
scope = $rootScope
ctrl = $controller 'enterpriseCtrl', {$scope: scope, Enterprise: Enterprise, EnterprisePaymentMethods: PaymentMethods, EnterpriseShippingMethods: ShippingMethods}
describe "initialisation", ->
it "stores enterprise", ->
@@ -34,56 +30,50 @@ describe "enterpriseCtrl", ->
it "stores shipping methods", ->
expect(scope.ShippingMethods).toBe ShippingMethods.shippingMethods
it "sets the selected property of each payment method", ->
expect(PaymentMethods.paymentMethods[0].selected).toBe true
expect(PaymentMethods.paymentMethods[1].selected).toBe false
expect(PaymentMethods.paymentMethods[2].selected).toBe true
expect(PaymentMethods.paymentMethods[3].selected).toBe false
describe "adding managers", ->
u1 = u2 = u3 = null
beforeEach ->
u1 = { id: 1, email: 'name1@email.com' }
u2 = { id: 2, email: 'name2@email.com' }
u3 = { id: 3, email: 'name3@email.com' }
Enterprise.enterprise.users = [u1, u2 ,u3]
it "sets the selected property of each shipping method", ->
expect(ShippingMethods.shippingMethods[0].selected).toBe false
expect(ShippingMethods.shippingMethods[1].selected).toBe true
expect(ShippingMethods.shippingMethods[2].selected).toBe false
expect(ShippingMethods.shippingMethods[3].selected).toBe true
it "adds a user to the list", ->
u4 = { id: 4, email: "name4@email.com" }
scope.addManager u4
expect(Enterprise.enterprise.users).toContain u4
describe "determining payment method colour", ->
it "returns 'blue' when at least one payment method is selected", ->
scope.PaymentMethods = [ { id: 1 } ]
spyOn(scope, "selectedPaymentMethodsCount").andReturn 1
expect(scope.paymentMethodsColor()).toBe "blue"
it "ignores object without an id", ->
u4 = { not_id: 4, email: "name4@email.com" }
scope.addManager u4
expect(Enterprise.enterprise.users).not.toContain u4
it "returns 'red' when no payment methods are selected", ->
scope.PaymentMethods = [ { id: 1 } ]
spyOn(scope, "selectedPaymentMethodsCount").andReturn 0
expect(scope.paymentMethodsColor()).toBe "red"
it "it ignores objects without an email", ->
u4 = { id: 4, not_email: "name4@email.com" }
scope.addManager u4
expect(Enterprise.enterprise.users).not.toContain u4
it "returns 'red' when no payment methods exist", ->
scope.PaymentMethods = [ ]
spyOn(scope, "selectedPaymentMethodsCount").andReturn 1
expect(scope.paymentMethodsColor()).toBe "red"
it "ignores objects that are already in the list, and alerts the user", ->
spyOn(window, "alert").andCallThrough()
u4 = { id: 3, email: "email-doesn't-matter.com" }
scope.addManager u4
expect(Enterprise.enterprise.users).not.toContain u4
expect(window.alert).toHaveBeenCalledWith "email-doesn't-matter.com is already a manager!"
describe "counting selected payment methods", ->
it "counts only payment methods with selected: true", ->
scopePaymentMethods = [ { selected: true }, { selected: false }, { selected: false }, { selected: true } ]
expect(scope.selectedPaymentMethodsCount()).toBe 2
describe "determining shipping method colour", ->
it "returns 'blue' when at least one shipping method is selected", ->
scope.ShippingMethods = [ { id: 1 } ]
spyOn(scope, "selectedShippingMethodsCount").andReturn 1
expect(scope.shippingMethodsColor()).toBe "blue"
describe "removing managers", ->
u1 = u2 = u3 = null
beforeEach ->
u1 = { id: 1, email: 'name1@email.com' }
u2 = { id: 2, email: 'name2@email.com' }
u3 = { id: 3, email: 'name3@email.com' }
Enterprise.enterprise.users = [u1, u2 ,u3]
it "returns 'red' when no shipping methods are selected", ->
scope.ShippingMethods = [ { id: 1 } ]
spyOn(scope, "selectedShippingMethodsCount").andReturn 0
expect(scope.shippingMethodsColor()).toBe "red"
it "returns 'red' when no shipping method exist", ->
scope.ShippingMethods = [ ]
spyOn(scope, "selectedShippingMethodsCount").andReturn 1
expect(scope.shippingMethodsColor()).toBe "red"
it "removes a user with the given id", ->
scope.removeManager {id: 2}
expect(Enterprise.enterprise.users).not.toContain u2
describe "counting selected shipping methods", ->
it "counts only shipping methods with selected: true", ->
scope.ShippingMethods = [ { selected: true }, { selected: true }, { selected: false }, { selected: true } ]
expect(scope.selectedShippingMethodsCount()).toBe 3
it "does nothing when given object has no id attribute", ->
scope.removeManager {not_id: 2}
expect(Enterprise.enterprise.users).toEqual [u1,u2,u3]

View File

@@ -0,0 +1,57 @@
describe "permalinkCtrl", ->
ctrl = null
$scope = null
Enterprise = null
PermalinkChecker = null
$httpBackend = null
$q = null
beforeEach ->
module('admin.enterprises')
Enterprise =
permalink: "something"
inject ($rootScope, $controller, _$q_, _PermalinkChecker_) ->
$scope = $rootScope
$scope.Enterprise = Enterprise
$q = _$q_
PermalinkChecker = _PermalinkChecker_
$ctrl = $controller 'permalinkCtrl', {$scope: $scope, PermalinkChecker: PermalinkChecker}
describe "checking permalink", ->
deferred = null
beforeEach ->
# Build a deferred object
deferred = $q.defer()
it "sends a request to PermalinkChecker when permalink is changed", ->
deferred.resolve("")
promise = deferred.promise
spyOn(PermalinkChecker, "check").andReturn promise
$scope.$apply Enterprise.permalink = "somethingelse" # Change the permalink
expect(PermalinkChecker.check).toHaveBeenCalled()
it "sets available to '' when PermalinkChecker resolves permalink to the existing permalink on Enterprise ", ->
deferred.resolve({permalink: "something"})
promise = deferred.promise
spyOn(PermalinkChecker, "check").andReturn promise
$scope.$apply Enterprise.permalink = "somethingelse" # Change the permalink
expect($scope.availability).toEqual ""
it "sets available and permalink when PermalinkChecker resolves", ->
deferred.resolve({ available: "Available", permalink: "permalink"})
promise = deferred.promise
spyOn(PermalinkChecker, "check").andReturn promise
$scope.$apply Enterprise.permalink = "somethingelse" # Change the permalink
expect(Enterprise.permalink).toEqual "permalink"
expect($scope.availability).toEqual "Available"
it "does nothing when PermalinkChecker rejects", ->
$scope.availability = "Some Availability"
deferred.reject()
promise = deferred.promise
spyOn(PermalinkChecker, "check").andReturn promise
$scope.$apply Enterprise.permalink = "somethingelse" # Change the permalink
expect($scope.availability).toEqual "Some Availability"
expect(Enterprise.permalink).toEqual "somethingelse"

View File

@@ -0,0 +1,41 @@
describe "menuCtrl", ->
ctrl = null
scope = null
Enterprise = null
SideMenu = SideMenu
beforeEach ->
module('admin.enterprises')
Enterprise =
enterprise:
payment_method_ids: [ 1, 3 ]
shipping_method_ids: [ 2, 4 ]
# PaymentMethods =
# paymentMethods: [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 } ]
# ShippingMethods =
# shippingMethods: [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 } ]
inject ($rootScope, $controller, _SideMenu_) ->
scope = $rootScope
SideMenu = _SideMenu_
spyOn(SideMenu, "select").andCallThrough()
spyOn(SideMenu, "setItems").andCallThrough()
ctrl = $controller 'sideMenuCtrl', {$scope: scope, Enterprise: Enterprise, SideMenu: SideMenu, enterprisePermissions: {}}
describe "initialisation", ->
it "stores enterprise", ->
expect(scope.Enterprise).toEqual Enterprise.enterprise
it "sets the item list", ->
expect(SideMenu.setItems).toHaveBeenCalled
expect(scope.menu.items).toBe SideMenu.items
it "sets the initally selected value", ->
expect(SideMenu.select).toHaveBeenCalledWith 0
describe "selecting an item", ->
it "selects an item by performing setting the selected property on the item to true", ->
scope.select 4
expect(SideMenu.select).toHaveBeenCalledWith 4
expect(scope.menu.items[4].selected).toBe true

View File

@@ -0,0 +1,45 @@
describe "EnterprisePaymentMethods service", ->
Enterprise = null
PaymentMethods = null
EnterprisePaymentMethods = null
beforeEach ->
Enterprise =
enterprise:
payment_method_ids: [ 1, 3 ]
PaymentMethods =
paymentMethods: [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 } ]
module 'admin.enterprises'
module ($provide) ->
$provide.value 'PaymentMethods', PaymentMethods
$provide.value 'Enterprise', Enterprise
null
inject (_EnterprisePaymentMethods_) ->
EnterprisePaymentMethods = _EnterprisePaymentMethods_
describe "selecting payment methods", ->
it "sets the selected property of each payment method", ->
expect(PaymentMethods.paymentMethods[0].selected).toBe true
expect(PaymentMethods.paymentMethods[1].selected).toBe false
expect(PaymentMethods.paymentMethods[2].selected).toBe true
expect(PaymentMethods.paymentMethods[3].selected).toBe false
describe "determining payment method colour", ->
it "returns 'blue' when at least one payment method is selected", ->
spyOn(EnterprisePaymentMethods, "selectedCount").andReturn 1
expect(EnterprisePaymentMethods.displayColor()).toBe "blue"
it "returns 'red' when no payment methods are selected", ->
spyOn(EnterprisePaymentMethods, "selectedCount").andReturn 0
expect(EnterprisePaymentMethods.displayColor()).toBe "red"
it "returns 'red' when no payment methods exist", ->
EnterprisePaymentMethods.paymentMethods = []
spyOn(EnterprisePaymentMethods, "selectedCount").andReturn 1
expect(EnterprisePaymentMethods.displayColor()).toBe "red"
describe "counting selected payment methods", ->
it "counts only payment methods with selected: true", ->
expect(EnterprisePaymentMethods.selectedCount()).toBe 2

View File

@@ -0,0 +1,45 @@
describe "EnterpriseShippingMethods service", ->
Enterprise = null
ShippingMethods = null
EnterpriseShippingMethods = null
beforeEach ->
Enterprise =
enterprise:
shipping_method_ids: [ 1, 3 ]
ShippingMethods =
shippingMethods: [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 } ]
module 'admin.enterprises'
module ($provide) ->
$provide.value 'ShippingMethods', ShippingMethods
$provide.value 'Enterprise', Enterprise
null
inject (_EnterpriseShippingMethods_) ->
EnterpriseShippingMethods = _EnterpriseShippingMethods_
describe "selecting shipping methods", ->
it "sets the selected property of each shipping method", ->
expect(ShippingMethods.shippingMethods[0].selected).toBe true
expect(ShippingMethods.shippingMethods[1].selected).toBe false
expect(ShippingMethods.shippingMethods[2].selected).toBe true
expect(ShippingMethods.shippingMethods[3].selected).toBe false
describe "determining shipping method colour", ->
it "returns 'blue' when at least one shipping method is selected", ->
spyOn(EnterpriseShippingMethods, "selectedCount").andReturn 1
expect(EnterpriseShippingMethods.displayColor()).toBe "blue"
it "returns 'red' when no shipping methods are selected", ->
spyOn(EnterpriseShippingMethods, "selectedCount").andReturn 0
expect(EnterpriseShippingMethods.displayColor()).toBe "red"
it "returns 'red' when no shipping methods exist", ->
EnterpriseShippingMethods.shippingMethods = []
spyOn(EnterpriseShippingMethods, "selectedCount").andReturn 1
expect(EnterpriseShippingMethods.displayColor()).toBe "red"
describe "counting selected shipping methods", ->
it "counts only shipping methods with selected: true", ->
expect(EnterpriseShippingMethods.selectedCount()).toBe 2

View File

@@ -3,10 +3,12 @@ describe "Enterprise service", ->
enterprise = { name: "test ent name" }
beforeEach ->
module 'admin.enterprises'
angular.module('admin.enterprises').value('enterprise', enterprise)
module ($provide) ->
$provide.value 'enterprise', enterprise
null
inject ($injector) ->
Enterprise = $injector.get("Enterprise")
Enterprise = $injector.get("Enterprise")
it "stores enterprise value as Enterprise.enterprise", ->
expect(Enterprise.enterprise).toBe enterprise
expect(Enterprise.enterprise).toBe enterprise

View File

@@ -0,0 +1,14 @@
describe "Permalink Checker service", ->
PermalinkChecker = null
$httpBackend = null
beforeEach ->
module 'admin.enterprises'
inject ($injector, _$httpBackend_) ->
$httpBackend = _$httpBackend_
PermalinkChecker = $injector.get("PermalinkChecker")
it "sends an http request to check the permalink", ->
permalink = "this-is-a-permalink"
$httpBackend.expectGET "/enterprises/check_permalink?permalink=#{permalink}"
PermalinkChecker.check(permalink)

View File

@@ -0,0 +1,49 @@
describe "AdminSimpleCreateOrderCycleCtrl", ->
ctrl = null
scope = {}
OrderCycle = {}
Enterprise = {}
EnterpriseFee = {}
incoming_exchange = {}
outgoing_exchange = {}
beforeEach ->
scope = {}
OrderCycle =
order_cycle:
incoming_exchanges: [incoming_exchange]
outgoing_exchanges: [outgoing_exchange]
addSupplier: jasmine.createSpy()
addDistributor: jasmine.createSpy()
setExchangeVariants: jasmine.createSpy()
Enterprise =
index: jasmine.createSpy()
suppliedVariants: jasmine.createSpy().andReturn('supplied variants')
EnterpriseFee =
index: jasmine.createSpy()
module('admin.order_cycles')
inject ($controller) ->
ctrl = $controller 'AdminSimpleCreateOrderCycleCtrl', {$scope: scope, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee}
describe "initialisation", ->
enterprise = {id: 123}
enterprises = {123: enterprise}
beforeEach ->
scope.init(enterprises)
it "sets up an incoming and outgoing exchange", ->
expect(OrderCycle.addSupplier).toHaveBeenCalledWith(enterprise.id)
expect(OrderCycle.addDistributor).toHaveBeenCalledWith(enterprise.id)
expect(scope.outgoing_exchange).toEqual outgoing_exchange
it "selects all variants", ->
expect(Enterprise.suppliedVariants).
toHaveBeenCalledWith(enterprise.id)
expect(OrderCycle.setExchangeVariants).
toHaveBeenCalledWith(incoming_exchange, 'supplied variants', true)
it "sets the coordinator", ->
expect(OrderCycle.order_cycle.coordinator_id).toEqual enterprise.id

View File

@@ -0,0 +1,38 @@
describe "AdminSimpleEditOrderCycleCtrl", ->
ctrl = null
scope = {}
location = {}
OrderCycle = {}
Enterprise = {}
EnterpriseFee = {}
incoming_exchange = {}
outgoing_exchange = {}
beforeEach ->
scope = {}
location =
absUrl: ->
'example.com/admin/order_cycles/27/edit'
OrderCycle =
order_cycle:
incoming_exchanges: [incoming_exchange]
outgoing_exchanges: [outgoing_exchange]
load: jasmine.createSpy()
Enterprise =
index: jasmine.createSpy()
EnterpriseFee =
index: jasmine.createSpy()
module('admin.order_cycles')
inject ($controller) ->
ctrl = $controller 'AdminSimpleEditOrderCycleCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee}
describe "initialisation", ->
enterprise = {id: 123}
enterprises = {123: enterprise}
beforeEach ->
scope.init(enterprises)
it "sets the outgoing exchange", ->
expect(scope.outgoing_exchange).toEqual outgoing_exchange

View File

@@ -0,0 +1,204 @@
describe "BulkProducts service", ->
BulkProducts = $httpBackend = null
beforeEach ->
module "ofn.admin"
beforeEach inject (_BulkProducts_, _$httpBackend_) ->
BulkProducts = _BulkProducts_
$httpBackend = _$httpBackend_
describe "fetching products", ->
beforeEach ->
spyOn BulkProducts, 'addProducts'
it "makes a standard call to dataFetcher when no filters exist", ->
$httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond "list of products"
BulkProducts.fetch [], ->
$httpBackend.flush()
it "makes more calls to dataFetcher if more pages exist", ->
$httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond { products: [], pages: 2 }
$httpBackend.expectGET("/api/products/bulk_products?page=2;per_page=20;").respond { products: ["list of products"] }
BulkProducts.fetch [], ->
$httpBackend.flush()
it "applies filters when they are supplied", ->
filter =
property:
name: "Name"
db_column: "name"
predicate:
name: "Equals"
predicate: "eq"
value: "Product1"
$httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;q[name_eq]=Product1;").respond "list of products"
BulkProducts.fetch [filter], ->
$httpBackend.flush()
describe "cloning products", ->
it "clones products using a http get request to /admin/products/(permalink)/clone.json", ->
BulkProducts.products = [
id: 13
permalink_live: "oranges"
]
$httpBackend.expectGET("/admin/products/oranges/clone.json").respond 200,
product:
id: 17
name: "new_product"
$httpBackend.expectGET("/api/products/17?template=bulk_show").respond 200, [
id: 17
name: "new_product"
]
BulkProducts.cloneProduct BulkProducts.products[0]
$httpBackend.flush()
it "adds the product", ->
originalProduct =
id: 16
permalink_live: "oranges"
clonedProduct =
id: 17
spyOn(BulkProducts, "addProducts")
BulkProducts.products = [originalProduct]
$httpBackend.expectGET("/admin/products/oranges/clone.json").respond 200,
product: clonedProduct
$httpBackend.expectGET("/api/products/17?template=bulk_show").respond 200, clonedProduct
BulkProducts.cloneProduct BulkProducts.products[0]
$httpBackend.flush()
expect(BulkProducts.addProducts).toHaveBeenCalledWith [clonedProduct]
describe "preparing products", ->
beforeEach ->
spyOn BulkProducts, "loadVariantUnit"
it "calls loadVariantUnit for the product", ->
product = {id: 123}
BulkProducts.unpackProduct product
expect(BulkProducts.loadVariantUnit).toHaveBeenCalled()
describe "loading variant unit", ->
describe "setting product variant_unit_with_scale field", ->
it "sets by combining variant_unit and variant_unit_scale", ->
product =
variant_unit: "volume"
variant_unit_scale: .001
BulkProducts.loadVariantUnit product
expect(product.variant_unit_with_scale).toEqual "volume_0.001"
it "sets to null when variant_unit is null", ->
product = {variant_unit: null, variant_unit_scale: 1000}
BulkProducts.loadVariantUnit product
expect(product.variant_unit_with_scale).toBeNull()
it "sets to variant_unit when variant_unit_scale is null", ->
product = {variant_unit: 'items', variant_unit_scale: null, variant_unit_name: 'foo'}
BulkProducts.loadVariantUnit product
expect(product.variant_unit_with_scale).toEqual "items"
it "sets to variant_unit when variant_unit is 'items'", ->
product = {variant_unit: 'items', variant_unit_scale: 1000, variant_unit_name: 'foo'}
BulkProducts.loadVariantUnit product
expect(product.variant_unit_with_scale).toEqual "items"
it "loads data for variants (incl. master)", ->
spyOn BulkProducts, "loadVariantUnitValues"
spyOn BulkProducts, "loadVariantUnitValue"
product =
variant_unit_scale: 1.0
master: {id: 1, unit_value: 1, unit_description: '(one)'}
variants: [{id: 2, unit_value: 2, unit_description: '(two)'}]
BulkProducts.loadVariantUnit product
expect(BulkProducts.loadVariantUnitValues).toHaveBeenCalledWith product
expect(BulkProducts.loadVariantUnitValue).toHaveBeenCalledWith product, product.master
it "loads data for variants (excl. master)", ->
spyOn BulkProducts, "loadVariantUnitValue"
product =
variant_unit_scale: 1.0
master: {id: 1, unit_value: 1, unit_description: '(one)'}
variants: [{id: 2, unit_value: 2, unit_description: '(two)'}]
BulkProducts.loadVariantUnitValues product
expect(BulkProducts.loadVariantUnitValue).toHaveBeenCalledWith product, product.variants[0]
expect(BulkProducts.loadVariantUnitValue).not.toHaveBeenCalledWith product, product.master
describe "setting variant unit_value_with_description", ->
it "sets by combining unit_value and unit_description", ->
product =
variant_unit_scale: 1.0
variants: [{id: 1, unit_value: 1, unit_description: '(bottle)'}]
BulkProducts.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0]).toEqual
id: 1
unit_value: 1
unit_description: '(bottle)'
unit_value_with_description: '1 (bottle)'
it "uses unit_value when description is missing", ->
product =
variant_unit_scale: 1.0
variants: [{id: 1, unit_value: 1}]
BulkProducts.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0].unit_value_with_description).toEqual '1'
it "uses unit_description when value is missing", ->
product =
variant_unit_scale: 1.0
variants: [{id: 1, unit_description: 'Small'}]
BulkProducts.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0].unit_value_with_description).toEqual 'Small'
it "converts values from base value to chosen unit", ->
product =
variant_unit_scale: 1000.0
variants: [{id: 1, unit_value: 2500}]
BulkProducts.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0].unit_value_with_description).toEqual '2.5'
it "displays a unit_value of zero", ->
product =
variant_unit_scale: 1.0
variants: [{id: 1, unit_value: 0}]
BulkProducts.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0].unit_value_with_description).toEqual '0'
describe "calculating the scaled unit value for a variant", ->
it "returns the scaled value when variant has a unit_value", ->
product = {variant_unit_scale: 0.001}
variant = {unit_value: 5}
expect(BulkProducts.variantUnitValue(product, variant)).toEqual 5000
it "returns the unscaled value when the product has no scale", ->
product = {}
variant = {unit_value: 5}
expect(BulkProducts.variantUnitValue(product, variant)).toEqual 5
it "returns zero when the value is zero", ->
product = {}
variant = {unit_value: 0}
expect(BulkProducts.variantUnitValue(product, variant)).toEqual 0
it "returns null when the variant has no unit_value", ->
product = {}
variant = {}
expect(BulkProducts.variantUnitValue(product, variant)).toEqual null
describe "fetching a product by id", ->
it "returns the product when it is present", ->
product = {id: 123}
BulkProducts.products = [product]
expect(BulkProducts.find(123)).toEqual product
it "returns null when the product is not present", ->
BulkProducts.products = []
expect(BulkProducts.find(123)).toBeNull()

View File

@@ -0,0 +1,75 @@
describe "maintaining a list of dirty variant overrides", ->
DirtyVariantOverrides = null
variantOverride =
variant_id: 1
hub_id: 2
price: 3
count_on_hand: 4
beforeEach ->
module "ofn.admin"
beforeEach inject (_DirtyVariantOverrides_) ->
DirtyVariantOverrides = _DirtyVariantOverrides_
it "adds new dirty variant overrides", ->
DirtyVariantOverrides.add variantOverride
expect(DirtyVariantOverrides.dirtyVariantOverrides).toEqual
2:
1:
variant_id: 1
hub_id: 2
price: 3
count_on_hand: 4
it "updates existing dirty variant overrides", ->
DirtyVariantOverrides.dirtyVariantOverrides =
2:
1:
variant_id: 5
hub_id: 6
price: 7
count_on_hand: 8
DirtyVariantOverrides.add variantOverride
expect(DirtyVariantOverrides.dirtyVariantOverrides).toEqual
2:
1:
variant_id: 1
hub_id: 2
price: 3
count_on_hand: 4
describe "with a number of variant overrides", ->
beforeEach ->
DirtyVariantOverrides.dirtyVariantOverrides =
2:
1:
variant_id: 5
hub_id: 6
price: 7
count_on_hand: 8
3:
variant_id: 9
hub_id: 10
price: 11
count_on_hand: 12
4:
5:
variant_id: 13
hub_id: 14
price: 15
count_on_hand: 16
it "counts dirty variant overrides", ->
expect(DirtyVariantOverrides.count()).toEqual 3
it "clears dirty variant overrides", ->
DirtyVariantOverrides.clear()
expect(DirtyVariantOverrides.dirtyVariantOverrides).toEqual {}
it "returns a flattened list of overrides", ->
expect(DirtyVariantOverrides.all()).toEqual [
{variant_id: 5, hub_id: 6, price: 7, count_on_hand: 8}
{variant_id: 9, hub_id: 10, price: 11, count_on_hand: 12}
{variant_id: 13, hub_id: 14, price: 15, count_on_hand: 16}
]

View File

@@ -0,0 +1,17 @@
describe "DisplayProperties", ->
DisplayProperties = null
beforeEach ->
module "ofn.admin"
beforeEach inject (_DisplayProperties_) ->
DisplayProperties = _DisplayProperties_
it "defaults showVariants to false", ->
expect(DisplayProperties.showVariants(123)).toEqual false
it "sets the showVariants value", ->
DisplayProperties.setShowVariants(123, true)
expect(DisplayProperties.showVariants(123)).toEqual true
DisplayProperties.setShowVariants(123, false)
expect(DisplayProperties.showVariants(123)).toEqual false

View File

@@ -14,3 +14,5 @@ describe "enterprise relationships", ->
it "presents permission names", ->
expect(EnterpriseRelationships.permission_presentation("add_to_order_cycle")).toEqual "to add to order cycle"
expect(EnterpriseRelationships.permission_presentation("manage_products")).toEqual "to manage products"
expect(EnterpriseRelationships.permission_presentation("edit_profile")).toEqual "to edit profile"
expect(EnterpriseRelationships.permission_presentation("create_variant_overrides")).toEqual "to override variant details"

View File

@@ -0,0 +1,22 @@
describe "indexer", ->
Indexer = null
beforeEach ->
module "ofn.admin"
beforeEach inject (_Indexer_) ->
Indexer = _Indexer_
it "indexes an array of objects by id", ->
objects = [{id: 1, name: 'one'}, {id: 2, name: 'two'}]
index = Indexer.index objects
expect(index).toEqual({1: {id: 1, name: 'one'}, 2: {id: 2, name: 'two'}})
it "indexes an array of objects by another field", ->
objects = [{widget_id: 1, name: 'one'}, {widget_id: 2, name: 'two'}]
index = Indexer.index objects, 'widget_id'
expect(index).toEqual({1: {widget_id: 1, name: 'one'}, 2: {widget_id: 2, name: 'two'}})
it "returns an object, not an array", ->
index = Indexer.index []
expect(index.constructor).not.toEqual(Array)

View File

@@ -0,0 +1,13 @@
describe "PagedFetcher service", ->
PagedFetcher = null
beforeEach ->
module "ofn.admin"
beforeEach inject (_PagedFetcher_) ->
PagedFetcher = _PagedFetcher_
describe "substituting a page in the URL", ->
it "replaces ::page:: with the given page number", ->
expect(PagedFetcher.urlForPage("http://example.com/foo?page=::page::&per_page=20", 12)).
toEqual "http://example.com/foo?page=12&per_page=20"

View File

@@ -0,0 +1,68 @@
describe "VariantOverrides service", ->
VariantOverrides = null
variantOverrides = [
{id: 1, hub_id: 10, variant_id: 100, price: 1, count_on_hand: 1}
{id: 2, hub_id: 10, variant_id: 200, price: 2, count_on_hand: 2}
{id: 3, hub_id: 20, variant_id: 300, price: 3, count_on_hand: 3}
]
beforeEach ->
module "ofn.admin"
module ($provide) ->
$provide.value "variantOverrides", variantOverrides
null
beforeEach inject (_VariantOverrides_) ->
VariantOverrides = _VariantOverrides_
it "indexes variant overrides by hub_id -> variant_id", ->
expect(VariantOverrides.variantOverrides).toEqual
10:
100: {id: 1, hub_id: 10, variant_id: 100, price: 1, count_on_hand: 1}
200: {id: 2, hub_id: 10, variant_id: 200, price: 2, count_on_hand: 2}
20:
300: {id: 3, hub_id: 20, variant_id: 300, price: 3, count_on_hand: 3}
it "ensures blank data available for some products", ->
hubs = [{id: 10}, {id: 20}, {id: 30}]
products = [
{
id: 1
variants: [{id: 100}, {id: 200}, {id: 300}, {id: 400}, {id: 500}]
}
]
VariantOverrides.ensureDataFor hubs, products
expect(VariantOverrides.variantOverrides).toEqual
10:
100: {id: 1, hub_id: 10, variant_id: 100, price: 1, count_on_hand: 1}
200: {id: 2, hub_id: 10, variant_id: 200, price: 2, count_on_hand: 2}
300: { hub_id: 10, variant_id: 300, price: '', count_on_hand: ''}
400: { hub_id: 10, variant_id: 400, price: '', count_on_hand: ''}
500: { hub_id: 10, variant_id: 500, price: '', count_on_hand: ''}
20:
100: { hub_id: 20, variant_id: 100, price: '', count_on_hand: ''}
200: { hub_id: 20, variant_id: 200, price: '', count_on_hand: ''}
300: {id: 3, hub_id: 20, variant_id: 300, price: 3, count_on_hand: 3}
400: { hub_id: 20, variant_id: 400, price: '', count_on_hand: ''}
500: { hub_id: 20, variant_id: 500, price: '', count_on_hand: ''}
30:
100: { hub_id: 30, variant_id: 100, price: '', count_on_hand: ''}
200: { hub_id: 30, variant_id: 200, price: '', count_on_hand: ''}
300: { hub_id: 30, variant_id: 300, price: '', count_on_hand: ''}
400: { hub_id: 30, variant_id: 400, price: '', count_on_hand: ''}
500: { hub_id: 30, variant_id: 500, price: '', count_on_hand: ''}
it "updates the IDs of variant overrides", ->
VariantOverrides.variantOverrides[2] = {}
VariantOverrides.variantOverrides[2][3] = {hub_id: 2, variant_id: 3, price: "4.0", count_on_hand: 5}
VariantOverrides.variantOverrides[2][8] = {hub_id: 2, variant_id: 8, price: "9.0", count_on_hand: 10}
updatedVos = [
{id: 1, hub_id: 2, variant_id: 3, price: "4.0", count_on_hand: 5}
{id: 6, hub_id: 2, variant_id: 8, price: "9.0", count_on_hand: 10}
]
VariantOverrides.updateIds updatedVos
expect(VariantOverrides.variantOverrides[2][3].id).toEqual 1
expect(VariantOverrides.variantOverrides[2][8].id).toEqual 6

View File

@@ -0,0 +1,93 @@
describe "SideMenu service", ->
SideMenu = null
beforeEach ->
module "admin.side_menu"
beforeEach inject (_SideMenu_) ->
SideMenu = _SideMenu_
describe "setting items", ->
it "sets the items", ->
items = [ { name: "Name 1"}, { name: "Name 2"} ]
SideMenu.setItems items
expect(SideMenu.items[0]).toBe items[0]
it "sets the the visible flag to true for each", ->
items = [ { name: "Name 1"}, { name: "Name 2"} ]
SideMenu.setItems items
expect(items[0].visible).toBe true
describe "selecting an item", ->
describe "when no item has been selected", ->
it "doesn't crash because of no selected item existing", ->
SideMenu.items = [ { name: "Name 1"}, { name: "Name 2"} ]
SideMenu.select(1)
it "sets selected to the new item", ->
SideMenu.items = [ { name: "Name 1"}, { name: "Name 2"} ]
SideMenu.select(1)
expect(SideMenu.find_by_name("Name 2")).toBe SideMenu.items[1]
it "switches the selected value of the newly selected item to true", ->
item1 = { name: "Name 1", selected: false }
item2 = { name: "Name 2", selected: false }
SideMenu.items = [ item1, item2 ]
SideMenu.select(1)
expect(item2.selected).toBe true
it "doesn't crash if given an index greater than the length of items", ->
SideMenu.items = [ { name: "Name 1"}, { name: "Name 2"} ]
SideMenu.select(12)
describe "when an item has been selected", ->
item1 = item2 = null
beforeEach ->
item1 = { name: "Name 1", selected: true }
item2 = { name: "Name 2", selected: false }
SideMenu.selected = item1
SideMenu.items = [ item1, item2 ]
SideMenu.select(1)
it "switches the selected value of the existing selected item to false", ->
expect(item1.selected).toBe false
it "switches the selected value of the newly selected item to true", ->
expect(item2.selected).toBe true
describe "finding by name", ->
it "returns the element that matches", ->
SideMenu.items = [ { name: "Name 1"}, { name: "Name 2"} ]
expect(SideMenu.find_by_name("Name 2")).toBe SideMenu.items[1]
it "returns one element even if two items are found", ->
SideMenu.items = [ { name: "Name 1"}, { name: "Name 1"} ]
expect(SideMenu.find_by_name("Name 1")).toBe SideMenu.items[0]
it "returns null if no items are found", ->
SideMenu.items = [ { name: "Name 1"}, { name: "Name 2"} ]
expect(SideMenu.find_by_name("Name 3")).toBe null
describe "hiding an item by name", ->
it "sets visible to false on the response from find_by_name", ->
mockItem = { visible: true }
spyOn(SideMenu, 'find_by_name').andReturn mockItem
SideMenu.hide_item_by_name()
expect(mockItem.visible).toBe false
it "doesn't crash if null is returned from find_by_name", ->
spyOn(SideMenu, 'find_by_name').andReturn null
SideMenu.hide_item_by_name()
describe "showing an item by name", ->
it "sets visible to false on the response from find_by_name", ->
mockItem = { visible: false }
spyOn(SideMenu, 'find_by_name').andReturn mockItem
SideMenu.show_item_by_name()
expect(mockItem.visible).toBe true
it "doesn't crash if null is returned from find_by_name", ->
spyOn(SideMenu, 'find_by_name').andReturn null
SideMenu.show_item_by_name()

View File

@@ -184,7 +184,7 @@ describe "filtering products for submission to database", ->
created_at: null
updated_at: null
count_on_hand: 0
producer: 5
producer_id: 5
group_buy: null
group_buy_unit_size: null
@@ -231,7 +231,7 @@ describe "filtering products for submission to database", ->
]
describe "AdminProductEditCtrl", ->
$ctrl = $scope = $timeout = $httpBackend = DirtyProducts = null
$ctrl = $scope = $timeout = $httpBackend = BulkProducts = DirtyProducts = DisplayProperties = null
beforeEach ->
module "ofn.admin"
@@ -241,12 +241,14 @@ describe "AdminProductEditCtrl", ->
$provide.value 'SpreeApiKey', 'API_KEY'
null
beforeEach inject((_$controller_, _$timeout_, $rootScope, _$httpBackend_, _DirtyProducts_) ->
beforeEach inject((_$controller_, _$timeout_, $rootScope, _$httpBackend_, _BulkProducts_, _DirtyProducts_, _DisplayProperties_) ->
$scope = $rootScope.$new()
$ctrl = _$controller_
$timeout = _$timeout_
$httpBackend = _$httpBackend_
BulkProducts = _BulkProducts_
DirtyProducts = _DirtyProducts_
DisplayProperties = _DisplayProperties_
$ctrl "AdminProductEditCtrl", {$scope: $scope, $timeout: $timeout}
)
@@ -262,42 +264,33 @@ describe "AdminProductEditCtrl", ->
describe "fetching products", ->
it "makes a standard call to dataFetcher when no filters exist", ->
$httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond "list of products"
$scope.fetchProducts()
$q = null
deferred = null
beforeEach inject((_$q_) ->
$q = _$q_
)
beforeEach ->
deferred = $q.defer()
deferred.resolve()
spyOn $scope, "resetProducts"
spyOn(BulkProducts, "fetch").andReturn deferred.promise
it "calls resetProducts after data has been received", ->
spyOn $scope, "resetProducts"
$httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond { products: "list of products" }
$scope.fetchProducts()
$httpBackend.flush()
expect($scope.resetProducts).toHaveBeenCalledWith "list of products"
it "calls makes more calls to dataFetcher if more pages exist", ->
$httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond { products: [], pages: 2 }
$httpBackend.expectGET("/api/products/bulk_products?page=2;per_page=20;").respond { products: ["list of products"] }
$scope.fetchProducts()
$httpBackend.flush()
it "applies filters when they are present", ->
filter = {property: $scope.filterableColumns[1], predicate:$scope.filterTypes[0], value:"Product1"}
$scope.currentFilters.push filter # Don't use addFilter as that is not what we are testing
expect($scope.currentFilters).toEqual [filter]
$httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;q[name_eq]=Product1;").respond "list of products"
$scope.fetchProducts()
$httpBackend.flush()
$scope.$digest()
expect($scope.resetProducts).toHaveBeenCalled()
it "sets the loading property to true before fetching products and unsets it when loading is complete", ->
$httpBackend.expectGET("/api/products/bulk_products?page=1;per_page=20;").respond "list of products"
$scope.fetchProducts()
expect($scope.loading).toEqual true
$httpBackend.flush()
$scope.$digest()
expect($scope.loading).toEqual false
describe "resetting products", ->
beforeEach ->
spyOn $scope, "unpackProduct"
spyOn DirtyProducts, "clear"
$scope.products = {}
$scope.resetProducts [
@@ -311,153 +304,9 @@ describe "AdminProductEditCtrl", ->
}
]
it "sets products to the value of 'data'", ->
expect($scope.products).toEqual [
{
id: 1
name: "P1"
}
{
id: 3
name: "P2"
}
]
it "resets dirtyProducts", ->
expect(DirtyProducts.clear).toHaveBeenCalled()
it "calls unpackProduct once for each product", ->
expect($scope.unpackProduct.calls.length).toEqual 2
describe "preparing products", ->
beforeEach ->
spyOn $scope, "loadVariantUnit"
it "initialises display properties for the product", ->
product = {id: 123}
$scope.displayProperties = {}
$scope.unpackProduct product
expect($scope.displayProperties[123]).toEqual {showVariants: false}
it "calls loadVariantUnit for the product", ->
product = {id: 123}
$scope.displayProperties = {}
$scope.unpackProduct product
expect($scope.loadVariantUnit.calls.length).toEqual 1
describe "loading variant unit", ->
describe "setting product variant_unit_with_scale field", ->
it "sets by combining variant_unit and variant_unit_scale", ->
product =
variant_unit: "volume"
variant_unit_scale: .001
$scope.loadVariantUnit product
expect(product.variant_unit_with_scale).toEqual "volume_0.001"
it "sets to null when variant_unit is null", ->
product = {variant_unit: null, variant_unit_scale: 1000}
$scope.loadVariantUnit product
expect(product.variant_unit_with_scale).toBeNull()
it "sets to variant_unit when variant_unit_scale is null", ->
product = {variant_unit: 'items', variant_unit_scale: null, variant_unit_name: 'foo'}
$scope.loadVariantUnit product
expect(product.variant_unit_with_scale).toEqual "items"
it "sets to variant_unit when variant_unit is 'items'", ->
product = {variant_unit: 'items', variant_unit_scale: 1000, variant_unit_name: 'foo'}
$scope.loadVariantUnit product
expect(product.variant_unit_with_scale).toEqual "items"
it "loads data for variants (incl. master)", ->
spyOn $scope, "loadVariantUnitValues"
spyOn $scope, "loadVariantUnitValue"
product =
variant_unit_scale: 1.0
master: {id: 1, unit_value: 1, unit_description: '(one)'}
variants: [{id: 2, unit_value: 2, unit_description: '(two)'}]
$scope.loadVariantUnit product
expect($scope.loadVariantUnitValues).toHaveBeenCalledWith product
expect($scope.loadVariantUnitValue).toHaveBeenCalledWith product, product.master
it "loads data for variants (excl. master)", ->
spyOn $scope, "loadVariantUnitValue"
product =
variant_unit_scale: 1.0
master: {id: 1, unit_value: 1, unit_description: '(one)'}
variants: [{id: 2, unit_value: 2, unit_description: '(two)'}]
$scope.loadVariantUnitValues product
expect($scope.loadVariantUnitValue).toHaveBeenCalledWith product, product.variants[0]
expect($scope.loadVariantUnitValue).not.toHaveBeenCalledWith product, product.master
describe "setting variant unit_value_with_description", ->
it "sets by combining unit_value and unit_description", ->
product =
variant_unit_scale: 1.0
variants: [{id: 1, unit_value: 1, unit_description: '(bottle)'}]
$scope.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0]).toEqual
id: 1
unit_value: 1
unit_description: '(bottle)'
unit_value_with_description: '1 (bottle)'
it "uses unit_value when description is missing", ->
product =
variant_unit_scale: 1.0
variants: [{id: 1, unit_value: 1}]
$scope.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0].unit_value_with_description).toEqual '1'
it "uses unit_description when value is missing", ->
product =
variant_unit_scale: 1.0
variants: [{id: 1, unit_description: 'Small'}]
$scope.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0].unit_value_with_description).toEqual 'Small'
it "converts values from base value to chosen unit", ->
product =
variant_unit_scale: 1000.0
variants: [{id: 1, unit_value: 2500}]
$scope.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0].unit_value_with_description).toEqual '2.5'
it "displays a unit_value of zero", ->
product =
variant_unit_scale: 1.0
variants: [{id: 1, unit_value: 0}]
$scope.loadVariantUnitValues product, product.variants[0]
expect(product.variants[0].unit_value_with_description).toEqual '0'
describe "calculating the scaled unit value for a variant", ->
it "returns the scaled value when variant has a unit_value", ->
product = {variant_unit_scale: 0.001}
variant = {unit_value: 5}
expect($scope.variantUnitValue(product, variant)).toEqual 5000
it "returns the unscaled value when the product has no scale", ->
product = {}
variant = {unit_value: 5}
expect($scope.variantUnitValue(product, variant)).toEqual 5
it "returns zero when the value is zero", ->
product = {}
variant = {unit_value: 0}
expect($scope.variantUnitValue(product, variant)).toEqual 0
it "returns null when the variant has no unit_value", ->
product = {}
variant = {}
expect($scope.variantUnitValue(product, variant)).toEqual null
describe "updating the product on hand count", ->
it "updates when product is not available on demand", ->
@@ -676,7 +525,7 @@ describe "AdminProductEditCtrl", ->
testProduct = {id: 123}
beforeEach ->
$scope.products = [testProduct]
BulkProducts.products = [testProduct]
it "extracts unit_value and unit_description from unit_value_with_description", ->
testProduct = {id: 123, variant_unit_scale: 1.0}
@@ -738,7 +587,7 @@ describe "AdminProductEditCtrl", ->
it "converts value from chosen unit to base unit", ->
testProduct = {id: 123, variant_unit_scale: 1000}
testVariant = {unit_value_with_description: "250.5"}
$scope.products = [testProduct]
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
expect(testVariant).toEqual
unit_value: 250500
@@ -748,7 +597,7 @@ describe "AdminProductEditCtrl", ->
it "does not convert value when using a non-scaled unit", ->
testProduct = {id: 123}
testVariant = {unit_value_with_description: "12"}
$scope.products = [testProduct]
BulkProducts.products = [testProduct]
$scope.packVariant(testProduct, testVariant)
expect(testVariant).toEqual
unit_value: 12
@@ -814,7 +663,7 @@ describe "AdminProductEditCtrl", ->
it "runs displaySuccess() when post returns success", ->
spyOn $scope, "displaySuccess"
spyOn $scope, "updateVariantLists"
spyOn BulkProducts, "updateVariantLists"
spyOn DirtyProducts, "clear"
$scope.products = [
{
@@ -841,7 +690,7 @@ describe "AdminProductEditCtrl", ->
$timeout.flush()
expect($scope.displaySuccess).toHaveBeenCalled()
expect(DirtyProducts.clear).toHaveBeenCalled()
expect($scope.updateVariantLists).toHaveBeenCalled()
expect(BulkProducts.updateVariantLists).toHaveBeenCalled()
it "runs displayFailure() when post returns an error", ->
spyOn $scope, "displayFailure"
@@ -859,20 +708,10 @@ describe "AdminProductEditCtrl", ->
$httpBackend.flush()
expect(window.alert).toHaveBeenCalledWith("Saving failed with the following error(s):\nan error\n")
describe "fetching a product by id", ->
it "returns the product when it is present", ->
product = {id: 123}
$scope.products = [product]
expect($scope.findProduct(123, $scope.products)).toEqual product
it "returns null when the product is not present", ->
$scope.products = []
expect($scope.findProduct(123, $scope.products)).toBeNull()
describe "adding variants", ->
beforeEach ->
$scope.displayProperties ||= {123: {}}
spyOn DisplayProperties, 'setShowVariants'
it "adds first and subsequent variants", ->
product = {id: 123, variants: []}
@@ -888,7 +727,7 @@ describe "AdminProductEditCtrl", ->
it "shows the variant(s)", ->
product = {id: 123, variants: []}
$scope.addVariant(product)
expect($scope.displayProperties[123].showVariants).toBe(true)
expect(DisplayProperties.setShowVariants).toHaveBeenCalledWith 123, true
describe "deleting products", ->
@@ -1023,85 +862,6 @@ describe "AdminProductEditCtrl", ->
describe "cloning products", ->
it "clones products using a http get request to /admin/products/(permalink)/clone.json", ->
$scope.products = [
id: 13
permalink_live: "oranges"
]
$httpBackend.expectGET("/admin/products/oranges/clone.json").respond 200,
product:
id: 17
name: "new_product"
$httpBackend.expectGET("/api/products/17?template=bulk_show").respond 200, [
id: 17
name: "new_product"
]
$scope.cloneProduct $scope.products[0]
$httpBackend.flush()
it "adds the newly created product to $scope.products and matches producer", ->
spyOn($scope, "unpackProduct").andCallThrough()
$scope.products = [
id: 13
permalink_live: "oranges"
]
$httpBackend.expectGET("/admin/products/oranges/clone.json").respond 200,
product:
id: 17
name: "new_product"
producer: 6
variants: [
id: 3
name: "V1"
]
$httpBackend.expectGET("/api/products/17?template=bulk_show").respond 200,
id: 17
name: "new_product"
producer: 6
variants: [
id: 3
name: "V1"
]
$scope.cloneProduct $scope.products[0]
$httpBackend.flush()
expect($scope.unpackProduct).toHaveBeenCalledWith
id: 17
name: "new_product"
variant_unit_with_scale: null
producer: 6
variants: [
id: 3
name: "V1"
unit_value_with_description: ""
]
expect($scope.products).toEqual [
{
id: 13
permalink_live: "oranges"
}
{
id: 17
name: "new_product"
variant_unit_with_scale: null
producer: 6
variants: [
id: 3
name: "V1"
unit_value_with_description: ""
]
}
]
describe "filtering products", ->
describe "clearing filters", ->
it "resets filter variables", ->

View File

@@ -3,7 +3,7 @@ describe "CheckoutCtrl", ->
scope = null
Checkout = null
CurrentUser = null
CurrentHubMock =
CurrentHubMock =
hub:
id: 1
storage = null
@@ -13,9 +13,9 @@ describe "CheckoutCtrl", ->
angular.module('Darkswarm').value('user', {})
angular.module('Darkswarm').value('currentHub', {id: 1})
module ($provide)->
$provide.value "CurrentHub", CurrentHubMock
$provide.value "CurrentHub", CurrentHubMock
null
Checkout =
Checkout =
submit: ->
navigate: ->
bindFieldsToLocalStorage: ->
@@ -25,35 +25,48 @@ describe "CheckoutCtrl", ->
user_id: 1
secrets:
card_number: "this is a secret"
describe "with user", ->
beforeEach ->
inject ($controller, $rootScope, _storage_) ->
storage = _storage_
spyOn(storage, "bind").andCallThrough()
scope = $rootScope.$new()
ctrl = $controller 'CheckoutCtrl', {$scope: scope, Checkout: Checkout, CurrentUser: {}}
it "delegates to the service on submit", ->
event =
scope = $rootScope.$new()
CurrentUser = { id: 1 }
ctrl = $controller 'CheckoutCtrl', {$scope: scope, Checkout: Checkout, CurrentUser: CurrentUser }
describe "submitting", ->
event =
preventDefault: ->
spyOn(Checkout, "submit")
scope.purchase(event)
expect(Checkout.submit).toHaveBeenCalled()
beforeEach ->
spyOn(Checkout, "submit")
scope.submitted = false
it "delegates to the service when valid", ->
scope.purchase(event, {$valid: true})
expect(Checkout.submit).toHaveBeenCalled()
expect(scope.submitted).toBe(true)
it "does nothing when invalid", ->
scope.purchase(event, {$valid: false})
expect(Checkout.submit).not.toHaveBeenCalled()
expect(scope.submitted).toBe(true)
it "is enabled", ->
expect(scope.enabled).toEqual true
describe "Local storage", ->
it "binds to localStorage when given a scope", ->
prefix = "order_#{scope.order.id}#{CurrentUser?.id}#{CurrentHubMock.hub.id}"
prefix = "order_#{scope.order.id}#{CurrentUser.id or ""}#{CurrentHubMock.hub.id}"
console.log prefix
field = scope.fieldsToBind[0]
expect(storage.bind).toHaveBeenCalledWith(scope, "Checkout.order.#{field}", {storeName: "#{prefix}_#{field}"})
expect(storage.bind).toHaveBeenCalledWith(scope, "Checkout.ship_address_same_as_billing", {storeName: "#{prefix}_sameasbilling", defaultValue: true})
it "it can retrieve data from localstorage", ->
prefix = "order_#{scope.order.id}#{CurrentUser?.id}#{CurrentHubMock.hub.id}"
expect(localStorage.getItem("#{prefix}_email")).toMatch "public"
prefix = "order_#{scope.order.id}#{CurrentUser.id or ""}#{CurrentHubMock.hub.id}"
expect(localStorage.getItem("#{prefix}_email")).toMatch "public"
it "does not store secrets in local storage", ->
Checkout.secrets =
@@ -65,8 +78,8 @@ describe "CheckoutCtrl", ->
describe "without user", ->
beforeEach ->
inject ($controller, $rootScope) ->
scope = $rootScope.$new()
ctrl = $controller 'CheckoutCtrl', {$scope: scope, Checkout: Checkout, CurrentUser: undefined}
scope = $rootScope.$new()
ctrl = $controller 'CheckoutCtrl', {$scope: scope, Checkout: Checkout, CurrentUser: {}}
it "is disabled", ->
expect(scope.enabled).toEqual false

View File

@@ -0,0 +1,19 @@
describe "ensuring absolute URL", ->
filter = null
beforeEach ->
module 'Darkswarm'
inject ($filter) ->
filter = $filter 'ext_url'
it "returns null when no URL given", ->
expect(filter(null, "http://")).toBeNull()
it "returns the URL as-is for http URLs", ->
expect(filter("http://example.com", "http://")).toEqual "http://example.com"
it "returns the URL as-is for https URLs", ->
expect(filter("https://example.com", "https://")).toEqual "https://example.com"
it "returns with URL with prefix added when a relative URL is given", ->
expect(filter("example.com", "http://")).toEqual "http://example.com"

View File

@@ -1,15 +1,17 @@
describe 'Cart service', ->
Cart = null
Variants = null
variant = {id: 1}
order = {
line_items: [
variant: variant
]
}
variant = null
order = null
beforeEach ->
module 'Darkswarm'
variant = {id: 1}
order = {
line_items: [
variant: variant
]
}
angular.module('Darkswarm').value('currentOrder', order)
inject ($injector)->
Variants = $injector.get("Variants")
@@ -23,10 +25,15 @@ describe 'Cart service', ->
it "creates and backreferences new line items if necessary", ->
Cart.register_variant(v2 = {id: 2})
expect(Cart.line_items[1].variant).toBe v2
expect(Cart.line_items[1].variant.line_item).toBe Cart.line_items[1]
expect(Cart.line_items[1].variant).toBe v2
expect(Cart.line_items[1].variant.line_item).toBe Cart.line_items[1]
it "returns a list of items actually in the cart", ->
expect(Cart.line_items_present()).toEqual []
order.line_items[0].quantity = 1
expect(Cart.line_items_present().length).toEqual 1
expect(Cart.line_items_present().length).toEqual
it "sums the quantity of each line item for cart total", ->
expect(Cart.line_items_present()).toEqual []
order.line_items[0].quantity = 2
expect(Cart.total_item_count()).toEqual 2

View File

@@ -38,7 +38,7 @@ describe 'OrderCycle controllers', ->
index: jasmine.createSpy('index').andReturn('enterprise fees list')
forEnterprise: jasmine.createSpy('forEnterprise').andReturn('enterprise fees for enterprise')
module('order_cycle')
module('admin.order_cycles')
inject ($controller) ->
ctrl = $controller 'AdminCreateOrderCycleCtrl', {$scope: scope, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee}
@@ -153,7 +153,8 @@ describe 'OrderCycle controllers', ->
expect(OrderCycle.removeDistributionOfVariant).toHaveBeenCalledWith('variant')
it 'Submits the order cycle via OrderCycle create', ->
scope.submit()
eventMock = { preventDefault: -> }
scope.submit(eventMock)
expect(OrderCycle.create).toHaveBeenCalled()
describe 'AdminEditOrderCycleCtrl', ->
@@ -198,7 +199,7 @@ describe 'OrderCycle controllers', ->
index: jasmine.createSpy('index').andReturn('enterprise fees list')
forEnterprise: jasmine.createSpy('forEnterprise').andReturn('enterprise fees for enterprise')
module('order_cycle')
module('admin.order_cycles')
inject ($controller) ->
ctrl = $controller 'AdminEditOrderCycleCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee}
@@ -313,7 +314,8 @@ describe 'OrderCycle controllers', ->
expect(OrderCycle.removeDistributionOfVariant).toHaveBeenCalledWith('variant')
it 'Submits the order cycle via OrderCycle update', ->
scope.submit()
eventMock = { preventDefault: -> }
scope.submit(eventMock)
expect(OrderCycle.update).toHaveBeenCalled()
@@ -323,7 +325,7 @@ describe 'OrderCycle services', ->
Enterprise = null
beforeEach ->
module 'order_cycle'
module 'admin.order_cycles'
inject ($injector, _$httpBackend_)->
Enterprise = $injector.get('Enterprise')
$httpBackend = _$httpBackend_
@@ -389,7 +391,7 @@ describe 'OrderCycle services', ->
EnterpriseFee = null
beforeEach ->
module 'order_cycle'
module 'admin.order_cycles'
inject ($injector, _$httpBackend_)->
EnterpriseFee = $injector.get('EnterpriseFee')
$httpBackend = _$httpBackend_
@@ -431,7 +433,7 @@ describe 'OrderCycle services', ->
beforeEach ->
$window = {navigator: {userAgent: 'foo'}}
module 'order_cycle', ($provide)->
module 'admin.order_cycles', ($provide)->
$provide.value('$window', $window)
null
@@ -526,7 +528,7 @@ describe 'OrderCycle services', ->
incoming: false
variants: {1: true, 2: false, 3: true}
enterprise_fees: []
describe "removing incoming exchanges", ->
beforeEach ->
exchange.incoming = true
@@ -844,4 +846,3 @@ describe 'OrderCycle services', ->
expect(order_cycle.outgoing_exchanges[0].enterprise_fees).toEqual [{id: 3}, {id: 4}]
expect(order_cycle.incoming_exchanges[0].enterprise_fee_ids).toBeUndefined()
expect(order_cycle.outgoing_exchanges[0].enterprise_fee_ids).toBeUndefined()

View File

@@ -0,0 +1,113 @@
require 'spec_helper'
include AuthenticationWorkflow
module OpenFoodNetwork
describe OrderCycleManagementReport do
context "as a site admin" do
let(:user) do
user = create(:user)
user.spree_roles << Spree::Role.find_or_create_by_name!("admin")
user
end
subject { OrderCycleManagementReport.new user }
describe "fetching orders" do
it "fetches completed orders" do
o1 = create(:order)
o2 = create(:order, completed_at: 1.day.ago)
subject.orders.should == [o2]
end
it "does not show cancelled orders" do
o1 = create(:order, state: "canceled", completed_at: 1.day.ago)
o2 = create(:order, completed_at: 1.day.ago)
subject.orders.should == [o2]
end
end
end
context "as an enterprise user" do
let!(:user) { create_enterprise_user }
subject { OrderCycleManagementReport.new user }
describe "fetching orders" do
let(:supplier) { create(:supplier_enterprise) }
let(:product) { create(:simple_product, supplier: supplier) }
let(:order) { create(:order, completed_at: 1.day.ago) }
it "only shows orders managed by the current user" do
d1 = create(:distributor_enterprise)
d1.enterprise_roles.create!(user: user)
d2 = create(:distributor_enterprise)
d2.enterprise_roles.create!(user: create(:user))
o1 = create(:order, distributor: d1, completed_at: 1.day.ago)
o2 = create(:order, distributor: d2, completed_at: 1.day.ago)
subject.should_receive(:filter).with([o1]).and_return([o1])
subject.orders.should == [o1]
end
it "does not show orders through a hub that the current user does not manage" do
# Given a supplier enterprise with an order for one of its products
supplier.enterprise_roles.create!(user: user)
order.line_items << create(:line_item, product: product)
# When I fetch orders, I should see no orders
subject.should_receive(:filter).with([]).and_return([])
subject.orders.should == []
end
end
describe "filtering orders" do
let!(:orders) { Spree::Order.scoped }
let!(:supplier) { create(:supplier_enterprise) }
let!(:oc1) { create(:simple_order_cycle) }
let!(:pm1) { create(:payment_method, name: "PM1") }
let!(:sm1) { create(:shipping_method, name: "ship1") }
let!(:order1) { create(:order, shipping_method: sm1, order_cycle: oc1) }
let!(:payment1) { create(:payment, order: order1, payment_method: pm1) }
it "returns all orders sans-params" do
subject.filter(orders).should == orders
end
it "filters to a specific order cycle" do
oc2 = create(:simple_order_cycle)
order2 = create(:order, order_cycle: oc2)
subject.stub(:params).and_return(order_cycle_id: oc1.id)
subject.filter(orders).should == [order1]
end
it "filters to a payment method" do
pm2 = create(:payment_method, name: "PM2")
order2 = create(:order)
payment2 = create(:payment, order: order2, payment_method: pm2)
subject.stub(:params).and_return(payment_method_name: pm1.name)
subject.filter(orders).should == [order1]
end
it "filters to a shipping method" do
sm2 = create(:shipping_method, name: "ship2")
order2 = create(:order, shipping_method: sm2)
subject.stub(:params).and_return(shipping_method_name: sm1.name)
subject.filter(orders).should == [order1]
end
it "should do all the filters at once" do
subject.stub(:params).and_return(order_cycle_id: oc1.id,
shipping_method_name: sm1.name,
payment_method_name: pm1.name)
subject.filter(orders).should == [order1]
end
end
end
end
end

View File

@@ -21,32 +21,119 @@ module OpenFoodNetwork
end
end
describe "finding enterprises whose profiles can be edited" do
let(:e) { double(:enterprise) }
it "returns managed and related enterprises with edit_profile permission" do
permissions.
should_receive(:managed_and_related_enterprises_with).
with(:edit_profile).
and_return([e])
permissions.editable_enterprises.should == [e]
end
end
describe "finding all producers for which we can create variant overrides" do
let(:e1) { create(:supplier_enterprise) }
let(:e2) { create(:supplier_enterprise) }
it "compiles the list from variant_override_enterprises_per_hub" do
permissions.stub(:variant_override_enterprises_per_hub) do
{1 => [e1.id], 2 => [e1.id, e2.id]}
end
permissions.variant_override_producers.sort.should == [e1, e2].sort
end
end
describe "finding enterprises for which variant overrides can be created, for each hub" do
let!(:hub) { create(:distributor_enterprise) }
let!(:producer) { create(:supplier_enterprise) }
let!(:er) { create(:enterprise_relationship, parent: producer, child: hub,
permissions_list: [:create_variant_overrides]) }
before do
permissions.stub(:managed_enterprises) { Enterprise.where(id: hub.id) }
end
it "returns enterprises as hub_id => [producer, ...]" do
permissions.variant_override_enterprises_per_hub.should ==
{hub.id => [producer.id]}
end
it "returns only permissions relating to managed enterprises" do
create(:enterprise_relationship, parent: e1, child: e2,
permissions_list: [:create_variant_overrides])
permissions.variant_override_enterprises_per_hub.should ==
{hub.id => [producer.id]}
end
it "returns only create_variant_overrides permissions" do
permissions.stub(:managed_enterprises) { Enterprise.where(id: [hub, e2]) }
create(:enterprise_relationship, parent: e1, child: e2,
permissions_list: [:manage_products])
permissions.variant_override_enterprises_per_hub.should ==
{hub.id => [producer.id]}
end
describe "hubs connected to the user by relationships only" do
# producer_managed can add hub to order cycle
# hub can create variant overrides for producer
# we manage producer_managed
# therefore, we should be able to create variant overrides for hub on producer's products
let!(:producer_managed) { create(:supplier_enterprise) }
let!(:er_oc) { create(:enterprise_relationship, parent: hub, child: producer_managed,
permissions_list: [:add_to_order_cycle]) }
before do
permissions.stub(:managed_enterprises) { Enterprise.where(id: producer_managed.id) }
end
it "allows the hub to create variant overrides for the producer" do
permissions.variant_override_enterprises_per_hub.should ==
{hub.id => [producer.id, producer_managed.id]}
end
end
it "also returns managed producers" do
producer2 = create(:supplier_enterprise)
permissions.stub(:managed_enterprises) { Enterprise.where(id: [hub, producer2]) }
permissions.variant_override_enterprises_per_hub.should ==
{hub.id => [producer.id, producer2.id]}
end
end
describe "finding exchanges of an order cycle that an admin can manage" do
let(:oc) { create(:simple_order_cycle) }
let!(:ex) { create(:exchange, order_cycle: oc, sender: e1, receiver: e2) }
before do
permissions.stub(:managed_enterprises) { [] }
permissions.stub(:related_enterprises_with) { [] }
permissions.stub(:managed_enterprises) { Enterprise.where('1=0') }
permissions.stub(:related_enterprises_with) { Enterprise.where('1=0') }
end
it "returns exchanges involving enterprises managed by the user" do
permissions.stub(:managed_enterprises) { [e1, e2] }
permissions.stub(:managed_enterprises) { Enterprise.where(id: [e1, e2]) }
permissions.order_cycle_exchanges(oc).should == [ex]
end
it "returns exchanges involving enterprises with E2E permission" do
permissions.stub(:related_enterprises_with) { [e1, e2] }
permissions.stub(:related_enterprises_with) { Enterprise.where(id: [e1, e2]) }
permissions.order_cycle_exchanges(oc).should == [ex]
end
it "does not return exchanges involving only the sender" do
permissions.stub(:managed_enterprises) { [e1] }
permissions.stub(:managed_enterprises) { Enterprise.where(id: [e1]) }
permissions.order_cycle_exchanges(oc).should == []
end
it "does not return exchanges involving only the receiver" do
permissions.stub(:managed_enterprises) { [e2] }
permissions.stub(:managed_enterprises) { Enterprise.where(id: [e2]) }
permissions.order_cycle_exchanges(oc).should == []
end
end

View File

@@ -18,6 +18,7 @@ module OpenFoodNetwork
"Producer Suburb",
"Product",
"Product Properties",
"Taxons",
"Variant Value",
"Price",
"Group Buy Unit Quantity",
@@ -33,7 +34,8 @@ module OpenFoodNetwork
variant.stub_chain(:product, :supplier, :name).and_return("Supplier")
variant.stub_chain(:product, :supplier, :address, :city).and_return("A city")
variant.stub_chain(:product, :name).and_return("Product Name")
variant.stub_chain(:product, :properties).and_return [double(name: "test"), double(name: "foo")]
variant.stub_chain(:product, :properties).and_return [double(name: "property1"), double(name: "property2")]
variant.stub_chain(:product, :taxons).and_return [double(name: "taxon1"), double(name: "taxon2")]
variant.stub_chain(:product, :group_buy_unit_size).and_return(21)
subject.stub(:variants).and_return [variant]
@@ -41,7 +43,8 @@ module OpenFoodNetwork
"Supplier",
"A city",
"Product Name",
"test, foo",
"property1, property2",
"taxon1, taxon2",
"Variant Name",
100,
21,
@@ -112,6 +115,12 @@ module OpenFoodNetwork
product2 = create(:simple_product, supplier: supplier)
subject.filter(Spree::Variant.scoped).sort.should == [product1.master, product2.master].sort
end
it "should filter deleted products" do
product1 = create(:simple_product, supplier: supplier)
product2 = create(:simple_product, supplier: supplier)
product2.delete
subject.filter(Spree::Variant.scoped).sort.should == [product1.master].sort
end
describe "based on report type" do
it "returns only variants on hand" do
product1 = create(:simple_product, supplier: supplier, on_hand: 99)

View File

@@ -0,0 +1,48 @@
require 'open_food_network/scope_variant_to_hub'
module OpenFoodNetwork
describe ScopeVariantToHub do
let(:hub) { create(:distributor_enterprise) }
let(:v) { create(:variant, price: 11.11, count_on_hand: 1) }
let(:vo) { create(:variant_override, hub: hub, variant: v, price: 22.22, count_on_hand: 2) }
describe "overriding price" do
it "returns the overridden price when one is present" do
vo
v.scope_to_hub hub
v.price.should == 22.22
end
it "returns the variant's price otherwise" do
v.scope_to_hub hub
v.price.should == 11.11
end
end
describe "overriding price_in" do
it "returns the overridden price when one is present" do
vo
v.scope_to_hub hub
v.price_in('AUD').amount.should == 22.22
end
it "returns the variant's price otherwise" do
v.scope_to_hub hub
v.price_in('AUD').amount.should == 11.11
end
end
describe "overriding stock levels" do
it "returns the overridden stock level when one is present" do
vo
v.scope_to_hub hub
v.count_on_hand.should == 2
end
it "returns the variant's stock level otherwise" do
v.scope_to_hub hub
v.count_on_hand.should == 1
end
end
end
end

View File

@@ -0,0 +1,44 @@
require 'open_food_network/user_balance_calculator'
require 'spec_helper'
module OpenFoodNetwork
describe UserBalanceCalculator do
describe "finding the account balance of a user with a hub" do
let!(:user1) { create(:user) }
let!(:hub1) { create(:distributor_enterprise) }
let!(:o1) { create(:order_with_totals_and_distribution, user: user1, distributor: hub1) } #total=10
let!(:o2) { create(:order_with_totals_and_distribution, user: user1, distributor: hub1) } #total=10
let!(:p1) { create(:payment, order: o1, amount: 15.00) }
let!(:p2) { create(:payment, order: o2, amount: 10.00) }
it "finds the user balance for this enterprise" do
UserBalanceCalculator.new(user1, hub1).balance.should == 5
end
context "with another hub" do
let!(:hub2) { create(:distributor_enterprise) }
let!(:o3) { create(:order_with_totals_and_distribution,
user: user1, distributor: hub2) } #total=10
let!(:p3) { create(:payment, order: o3, amount: 10.00) }
it "does not find the balance for other enterprises" do
UserBalanceCalculator.new(user1, hub2).balance.should == 0
end
end
context "with another user" do
let!(:user2) { create(:user) }
let!(:o4) { create(:order_with_totals_and_distribution,
user: user2, distributor: hub1) } #total=10
let!(:p3) { create(:payment, order: o4, amount: 20.00) }
it "does not find the balance for other users" do
UserBalanceCalculator.new(user2, hub1).balance.should == 10
end
end
end
end
end

View File

@@ -0,0 +1,132 @@
require 'spec_helper'
module OpenFoodNetwork
describe OrderAndDistributorReport do
include AuthenticationWorkflow
describe "users_and_enterprises" do
let!(:owners_and_enterprises) { double(:owners_and_enterprises) }
let!(:managers_and_enterprises) { double(:managers_and_enterprises) }
let!(:subject) { OpenFoodNetwork::UsersAndEnterprisesReport.new {} }
before do
subject.stub(:owners_and_enterprises) { owners_and_enterprises }
subject.stub(:managers_and_enterprises) { managers_and_enterprises }
end
it "should concatenate owner and manager queries" do
expect(subject).to receive(:owners_and_enterprises).once
expect(subject).to receive(:managers_and_enterprises).once
expect(owners_and_enterprises).to receive(:concat).with(managers_and_enterprises).and_return []
expect(subject).to receive(:sort).with []
subject.users_and_enterprises
end
end
describe "sorting results" do
let!(:subject) { OpenFoodNetwork::UsersAndEnterprisesReport.new {} }
it "sorts unconfirmed enterprises to the top" do
uae_mock = [
{ "confirmed_at" => "2015-01-01", "name" => "aaa" },
{ "confirmed_at" => nil, "name" => "bbb" }
]
expect(subject.sort uae_mock).to eq [ uae_mock[1], uae_mock[0] ]
end
it "then sorts by confirmation date" do
uae_mock = [
{ "confirmed_at" => "2015-01-01", "name" => "bbb" },
{ "confirmed_at" => "2015-01-02", "name" => "aaa" }
]
expect(subject.sort uae_mock).to eq [ uae_mock[1], uae_mock[0] ]
end
it "then sorts by name" do
uae_mock = [
{ "name" => "aaa", "relationship_type" => "bbb", "user_email" => "bbb" },
{ "name" => "bbb", "relationship_type" => "aaa", "user_email" => "aaa" }
]
expect(subject.sort uae_mock).to eq [ uae_mock[0], uae_mock[1] ]
end
it "then sorts by relationship type (reveresed)" do
uae_mock = [
{ "name" => "aaa", "relationship_type" => "bbb", "user_email" => "bbb" },
{ "name" => "aaa", "relationship_type" => "aaa", "user_email" => "aaa" },
{ "name" => "aaa", "relationship_type" => "bbb", "user_email" => "aaa" }
]
expect(subject.sort uae_mock).to eq [ uae_mock[2], uae_mock[0], uae_mock[1] ]
end
it "then sorts by user_email" do
uae_mock = [
{ "name" => "aaa", "relationship_type" => "bbb", "user_email" => "aaa" },
{ "name" => "aaa", "relationship_type" => "aaa", "user_email" => "aaa" },
{ "name" => "aaa", "relationship_type" => "aaa", "user_email" => "bbb" }
]
expect(subject.sort uae_mock).to eq [ uae_mock[0], uae_mock[1], uae_mock[2] ]
end
end
describe "filtering results" do
let!(:enterprise1) { create(:enterprise, owner: create_enterprise_user ) }
let!(:enterprise2) { create(:enterprise, owner: create_enterprise_user ) }
describe "for owners and enterprises" do
describe "by enterprise id" do
let!(:params) { { enterprise_id_in: [enterprise1.id.to_s] } }
let!(:subject) { OpenFoodNetwork::UsersAndEnterprisesReport.new params }
it "excludes enterprises that are not explicitly requested" do
results = subject.owners_and_enterprises.to_a.map{ |oae| oae["name"] }
expect(results).to include enterprise1.name
expect(results).to_not include enterprise2.name
end
end
describe "by user id" do
let!(:params) { { user_id_in: [enterprise1.owner.id.to_s] } }
let!(:subject) { OpenFoodNetwork::UsersAndEnterprisesReport.new params }
it "excludes enterprises that are not explicitly requested" do
results = subject.owners_and_enterprises.to_a.map{ |oae| oae["name"] }
expect(results).to include enterprise1.name
expect(results).to_not include enterprise2.name
end
end
end
describe "for managers and enterprises" do
describe "by enterprise id" do
let!(:params) { { enterprise_id_in: [enterprise1.id.to_s] } }
let!(:subject) { OpenFoodNetwork::UsersAndEnterprisesReport.new params }
it "excludes enterprises that are not explicitly requested" do
results = subject.managers_and_enterprises.to_a.map{ |mae| mae["name"] }
expect(results).to include enterprise1.name
expect(results).to_not include enterprise2.name
end
end
describe "by user id" do
let!(:manager1) { create_enterprise_user }
let!(:manager2) { create_enterprise_user }
let!(:params) { { user_id_in: [manager1.id.to_s] } }
let!(:subject) { OpenFoodNetwork::UsersAndEnterprisesReport.new params }
before do
enterprise1.enterprise_roles.build(user: manager1).save
enterprise2.enterprise_roles.build(user: manager2).save
end
it "excludes enterprises whose managers are not explicitly requested" do
results = subject.managers_and_enterprises.to_a.map{ |mae| mae["name"] }
expect(results).to include enterprise1.name
expect(results).to_not include enterprise2.name
end
end
end
end
end
end

View File

@@ -7,10 +7,35 @@ describe EnterpriseMailer do
ActionMailer::Base.deliveries = []
end
it "should send an email confirmation when given an enterprise" do
EnterpriseMailer.confirmation_instructions(enterprise, 'token').deliver
context "when given an enterprise without an unconfirmed_email" do
it "should send an email confirmation to email" do
EnterpriseMailer.confirmation_instructions(enterprise, 'token').deliver
ActionMailer::Base.deliveries.count.should == 1
mail = ActionMailer::Base.deliveries.first
expect(mail.subject).to eq "Please confirm your email for #{enterprise.name}"
expect(mail.to).to include enterprise.email
end
end
context "when given an enterprise with an unconfirmed_email" do
before do
enterprise.unconfirmed_email = "unconfirmed@email.com"
enterprise.save!
end
it "should send an email confirmation to unconfirmed_email" do
EnterpriseMailer.confirmation_instructions(enterprise, 'token').deliver
ActionMailer::Base.deliveries.count.should == 1
mail = ActionMailer::Base.deliveries.first
expect(mail.subject).to eq "Please confirm your email for #{enterprise.name}"
expect(mail.to).to include enterprise.unconfirmed_email
end
end
it "should send a welcome email when given an enterprise" do
EnterpriseMailer.welcome(enterprise).deliver
ActionMailer::Base.deliveries.count.should == 1
mail = ActionMailer::Base.deliveries.first
expect(mail.subject).to eq "Please confirm your email for #{enterprise.name}"
expect(mail.subject).to eq "#{enterprise.name} is now on #{Spree::Config[:site_name]}"
end
end

View File

@@ -20,18 +20,24 @@ describe Spree::OrderMailer do
ActionMailer::Base.deliveries = []
end
it "should send an email when given an order" do
Spree::OrderMailer.confirm_email(@order1.id).deliver
ActionMailer::Base.deliveries.count.should == 3
describe "order confirmation for customers" do
it "should send an email to the customer when given an order" do
Spree::OrderMailer.confirm_email_for_customer(@order1.id).deliver
ActionMailer::Base.deliveries.count.should == 1
ActionMailer::Base.deliveries.first.to.should == [@order1.email]
end
it "sets a reply-to of the enterprise email" do
Spree::OrderMailer.confirm_email_for_customer(@order1.id).deliver
ActionMailer::Base.deliveries.first.reply_to.should == [@distributor.email]
end
end
it "sets a reply-to of the enterprise email" do
Spree::OrderMailer.confirm_email(@order1.id).deliver
ActionMailer::Base.deliveries.first.reply_to.should == [@distributor.email]
end
it "ccs the enterprise" do
Spree::OrderMailer.confirm_email(@order1.id).deliver
ActionMailer::Base.deliveries.first.cc.should == [@distributor.email]
describe "order confirmation for shops" do
it "sends an email to the shop owner when given an order" do
Spree::OrderMailer.confirm_email_for_shop(@order1.id).deliver
ActionMailer::Base.deliveries.count.should == 1
ActionMailer::Base.deliveries.first.to.should == [@distributor.email]
end
end
end

View File

@@ -51,5 +51,14 @@ describe EnterpriseGroup do
EnterpriseGroup.on_front_page.should == [eg1]
end
it "finds a user's enterprise groups" do
user = create(:user)
user.spree_roles = []
eg1 = create(:enterprise_group, owner: user)
eg2 = create(:enterprise_group)
EnterpriseGroup.managed_by(user).should == [eg1]
end
end
end

View File

@@ -44,12 +44,18 @@ describe EnterpriseRelationship do
end
end
it "finds relationships that grant permissions to some enterprises" do
er1 = create(:enterprise_relationship, parent: e2, child: e1)
er2 = create(:enterprise_relationship, parent: e3, child: e2)
er3 = create(:enterprise_relationship, parent: e1, child: e3)
describe "finding by permission" do
let!(:er1) { create(:enterprise_relationship, parent: e2, child: e1) }
let!(:er2) { create(:enterprise_relationship, parent: e3, child: e2) }
let!(:er3) { create(:enterprise_relationship, parent: e1, child: e3) }
EnterpriseRelationship.permitting([e1, e2]).sort.should == [er1, er2]
it "finds relationships that grant permissions to some enterprises" do
EnterpriseRelationship.permitting([e1, e2]).sort.should == [er1, er2].sort
end
it "finds relationships that are granted by particular enterprises" do
EnterpriseRelationship.permitted_by([e1, e2]).sort.should == [er1, er3].sort
end
end
it "finds relationships that grant a particular permission" do

View File

@@ -8,16 +8,79 @@ describe Enterprise do
let!(:user) { create_enterprise_user( enterprise_limit: 2 ) }
let!(:enterprise) { create(:enterprise, owner: user) }
context "when the email address has not already been confirmed" do
it "sends a confirmation email" do
mail_message = double "Mail::Message"
expect(EnterpriseMailer).to receive(:confirmation_instructions).and_return mail_message
mail_message.should_receive :deliver
create(:enterprise, owner: user, email: "unknown@email.com", confirmed_at: nil )
end
it "does not send a welcome email" do
expect(EnterpriseMailer).to_not receive(:welcome)
create(:enterprise, owner: user, email: "unknown@email.com", confirmed_at: nil )
end
end
context "when the email address has already been confirmed" do
it "does not send a confirmation email" do
expect(EnterpriseMailer).to_not receive(:confirmation_instructions)
create(:enterprise, owner: user, email: enterprise.email, confirmed_at: nil)
end
it "sends a welcome email" do
mail_message = double "Mail::Message"
expect(EnterpriseMailer).to receive(:welcome).and_return mail_message
mail_message.should_receive :deliver
create(:enterprise, owner: user, email: enterprise.email, confirmed_at: nil)
end
end
end
describe "on update of email" do
let!(:user) { create_enterprise_user( enterprise_limit: 2 ) }
let!(:enterprise) { create(:enterprise, owner: user) }
it "when the email address has not already been confirmed" do
mail_message = double "Mail::Message"
EnterpriseMailer.should_receive(:confirmation_instructions).and_return mail_message
expect(EnterpriseMailer).to receive(:confirmation_instructions).and_return mail_message
mail_message.should_receive :deliver
create(:enterprise, owner: user, email: "unknown@email.com", confirmed_at: nil )
enterprise.update_attributes(email: "unknown@email.com")
end
it "when the email address has already been confirmed" do
EnterpriseMailer.should_not_receive(:confirmation_instructions)
e = create(:enterprise, owner: user, email: enterprise.email, confirmed_at: nil)
create(:enterprise, owner: user, email: "second.known.email@email.com") # Another enterpise with same owner but different email
expect(EnterpriseMailer).to_not receive(:confirmation_instructions)
enterprise.update_attributes!(email: "second.known.email@email.com")
end
end
describe "on email confirmation" do
let!(:user) { create_enterprise_user( enterprise_limit: 2 ) }
let!(:unconfirmed_enterprise) { create(:enterprise, owner: user, confirmed_at: nil) }
context "when we are confirming an email address for the first time for the enterprise" do
it "sends a welcome email" do
# unconfirmed_email is blank if we are not reconfirming an email
unconfirmed_enterprise.unconfirmed_email = nil
unconfirmed_enterprise.save!
mail_message = double "Mail::Message"
expect(EnterpriseMailer).to receive(:welcome).and_return mail_message
mail_message.should_receive :deliver
unconfirmed_enterprise.confirm!
end
end
context "when we are reconfirming the email address for the enterprise" do
it "does not send a welcome email" do
# unconfirmed_email is present if we are reconfirming an email
unconfirmed_enterprise.unconfirmed_email = "unconfirmed@email.com"
unconfirmed_enterprise.save!
expect(EnterpriseMailer).to_not receive(:welcome)
unconfirmed_enterprise.confirm!
end
end
end
end
@@ -96,21 +159,58 @@ describe Enterprise do
expect{
e2.owner = u1
e2.save!
}.to raise_error ActiveRecord::RecordInvalid, "Validation failed: You are not permitted to own own any more enterprises (limit is 1)."
}.to raise_error ActiveRecord::RecordInvalid, "Validation failed: #{u1.email} is not permitted to own any more enterprises (limit is 1)."
end
end
end
describe "validations" do
subject { FactoryGirl.create(:distributor_enterprise, :address => FactoryGirl.create(:address)) }
subject { FactoryGirl.create(:distributor_enterprise) }
it { should validate_presence_of(:name) }
it { should validate_presence_of(:email) }
it { should validate_uniqueness_of(:permalink) }
it { should ensure_length_of(:description).is_at_most(255) }
it "requires an owner" do
expect{
e = create(:enterprise, owner: nil)
}.to raise_error ActiveRecord::RecordInvalid, "Validation failed: Owner can't be blank"
end
describe "preferred_shopfront_taxon_order" do
it "empty strings are valid" do
enterprise = build(:enterprise, preferred_shopfront_taxon_order: "")
expect(enterprise).to be_valid
end
it "a single integer is valid" do
enterprise = build(:enterprise, preferred_shopfront_taxon_order: "11")
expect(enterprise).to be_valid
end
it "comma delimited integers are valid" do
enterprise = build(:enterprise, preferred_shopfront_taxon_order: "1,2,3")
expect(enterprise).to be_valid
enterprise = build(:enterprise, preferred_shopfront_taxon_order: "1,22,333")
expect(enterprise).to be_valid
end
it "commas at the beginning and end are disallowed" do
enterprise = build(:enterprise, preferred_shopfront_taxon_order: ",1,2,3")
expect(enterprise).to be_invalid
enterprise = build(:enterprise, preferred_shopfront_taxon_order: "1,2,3,")
expect(enterprise).to be_invalid
end
it "any other characters are invalid" do
enterprise = build(:enterprise, preferred_shopfront_taxon_order: "a1,2,3")
expect(enterprise).to be_invalid
enterprise = build(:enterprise, preferred_shopfront_taxon_order: ".1,2,3")
expect(enterprise).to be_invalid
enterprise = build(:enterprise, preferred_shopfront_taxon_order: " 1,2,3")
expect(enterprise).to be_invalid
end
end
end
describe "delegations" do
@@ -122,9 +222,19 @@ describe Enterprise do
it { should delegate(:state_name).to(:address) }
end
describe "callbacks" do
it "restores permalink to original value when it is changed and invalid" do
e1 = create(:enterprise, permalink: "taken")
e2 = create(:enterprise, permalink: "not_taken")
e2.permalink = "taken"
e2.save
expect(e2.permalink).to eq "not_taken"
end
end
describe "scopes" do
describe 'active' do
it 'find active enterprises' do
describe 'visible' do
it 'find visible enterprises' do
d1 = create(:distributor_enterprise, visible: false)
s1 = create(:supplier_enterprise)
Enterprise.visible.should == [s1]
@@ -153,6 +263,97 @@ describe Enterprise do
end
end
describe "activated" do
let!(:inactive_enterprise1) { create(:enterprise, sells: "unspecified", confirmed_at: Time.now) ;}
let!(:inactive_enterprise2) { create(:enterprise, sells: "none", confirmed_at: nil) }
let!(:active_enterprise) { create(:enterprise, sells: "none", confirmed_at: Time.now) }
it "finds enterprises that have a sells property other than 'unspecified' and that are confirmed" do
activated_enterprises = Enterprise.activated
expect(activated_enterprises).to include active_enterprise
expect(activated_enterprises).to_not include inactive_enterprise1
expect(activated_enterprises).to_not include inactive_enterprise2
end
end
describe "ready_for_checkout" do
let!(:e) { create(:enterprise) }
it "does not show enterprises with no payment methods" do
create(:shipping_method, distributors: [e])
Enterprise.ready_for_checkout.should_not include e
end
it "does not show enterprises with no shipping methods" do
create(:payment_method, distributors: [e])
Enterprise.ready_for_checkout.should_not include e
end
it "does not show enterprises with unavailable payment methods" do
create(:shipping_method, distributors: [e])
create(:payment_method, distributors: [e], active: false)
Enterprise.ready_for_checkout.should_not include e
end
it "shows enterprises with available payment and shipping methods" do
create(:shipping_method, distributors: [e])
create(:payment_method, distributors: [e])
Enterprise.ready_for_checkout.should include e
end
end
describe "not_ready_for_checkout" do
let!(:e) { create(:enterprise) }
it "shows enterprises with no payment methods" do
create(:shipping_method, distributors: [e])
Enterprise.not_ready_for_checkout.should include e
end
it "shows enterprises with no shipping methods" do
create(:payment_method, distributors: [e])
Enterprise.not_ready_for_checkout.should include e
end
it "shows enterprises with unavailable payment methods" do
create(:shipping_method, distributors: [e])
create(:payment_method, distributors: [e], active: false)
Enterprise.not_ready_for_checkout.should include e
end
it "does not show enterprises with available payment and shipping methods" do
create(:shipping_method, distributors: [e])
create(:payment_method, distributors: [e])
Enterprise.not_ready_for_checkout.should_not include e
end
end
describe "#ready_for_checkout?" do
let!(:e) { create(:enterprise) }
it "returns false for enterprises with no payment methods" do
create(:shipping_method, distributors: [e])
e.reload.should_not be_ready_for_checkout
end
it "returns false for enterprises with no shipping methods" do
create(:payment_method, distributors: [e])
e.reload.should_not be_ready_for_checkout
end
it "returns false for enterprises with unavailable payment methods" do
create(:shipping_method, distributors: [e])
create(:payment_method, distributors: [e], active: false)
e.reload.should_not be_ready_for_checkout
end
it "returns true for enterprises with available payment and shipping methods" do
create(:shipping_method, distributors: [e])
create(:payment_method, distributors: [e])
e.reload.should be_ready_for_checkout
end
end
describe "distributors_with_active_order_cycles" do
it "finds active distributors by order cycles" do
s = create(:supplier_enterprise)
@@ -390,6 +591,77 @@ describe Enterprise do
end
end
describe "callbacks" do
describe "after creation" do
let(:owner) { create(:user, enterprise_limit: 10) }
let(:hub1) { create(:distributor_enterprise, owner: owner) }
let(:hub2) { create(:distributor_enterprise, owner: owner) }
let(:hub3) { create(:distributor_enterprise, owner: owner) }
let(:producer1) { create(:supplier_enterprise, owner: owner) }
let(:producer2) { create(:supplier_enterprise, owner: owner) }
describe "when a producer is created" do
before do
hub1
hub2
end
it "creates links from the new producer to all hubs owned by the same user, granting all permissions" do
producer1
should_have_enterprise_relationship from: producer1, to: hub1, with: :all_permissions
should_have_enterprise_relationship from: producer1, to: hub2, with: :all_permissions
end
it "does not create any other links" do
expect do
producer1
end.to change(EnterpriseRelationship, :count).by(2)
end
end
describe "when a new hub is created" do
it "it creates links to the hub, from all producers owned by the same user, granting all permissions" do
producer1
producer2
hub1
should_have_enterprise_relationship from: producer1, to: hub1, with: :all_permissions
should_have_enterprise_relationship from: producer2, to: hub1, with: :all_permissions
end
it "creates links from the new hub to all hubs owned by the same user, granting all permissions" do
hub1
hub2
hub3
should_have_enterprise_relationship from: hub2, to: hub1, with: :all_permissions
should_have_enterprise_relationship from: hub3, to: hub1, with: :all_permissions
should_have_enterprise_relationship from: hub3, to: hub2, with: :all_permissions
end
it "does not create any other links" do
producer1
producer2
expect { hub1 }.to change(EnterpriseRelationship, :count).by(2) # 2 producer links
expect { hub2 }.to change(EnterpriseRelationship, :count).by(3) # 2 producer links + 1 hub link
expect { hub3 }.to change(EnterpriseRelationship, :count).by(4) # 2 producer links + 2 hub links
end
end
def should_have_enterprise_relationship(opts={})
er = EnterpriseRelationship.where(parent_id: opts[:from], child_id: opts[:to]).last
er.should_not be_nil
if opts[:with] == :all_permissions
er.permissions.map(&:name).sort.should == ['add_to_order_cycle', 'manage_products', 'edit_profile', 'create_variant_overrides'].sort
end
end
end
end
describe "has_supplied_products_on_hand?" do
before :each do
@supplier = create(:supplier_enterprise)
@@ -565,4 +837,47 @@ describe Enterprise do
non_producer_sell_none.category.should == :hub_profile
end
end
describe "finding and automatically assigning a permalink" do
let(:enterprise) { build(:enterprise, name: "Name To Turn Into A Permalink") }
it "assigns permalink when initialized" do
allow(Enterprise).to receive(:find_available_permalink).and_return("available_permalink")
Enterprise.should_receive(:find_available_permalink).with("Name To Turn Into A Permalink")
expect(
lambda { enterprise.send(:initialize_permalink) }
).to change{
enterprise.permalink
}.to(
"available_permalink"
)
end
describe "finding a permalink" do
let!(:enterprise1) { create(:enterprise, permalink: "permalink") }
let!(:enterprise2) { create(:enterprise, permalink: "permalink1") }
it "parameterizes the value provided" do
expect(Enterprise.find_available_permalink("Some Unused Permalink")).to eq "some-unused-permalink"
end
it "sets the permalink to 'my-enterprise' if parametized permalink is blank" do
expect(Enterprise.find_available_permalink("")).to eq "my-enterprise"
expect(Enterprise.find_available_permalink("$$%{$**}$%}")).to eq "my-enterprise"
end
it "finds and index value based on existing permalinks" do
expect(Enterprise.find_available_permalink("permalink")).to eq "permalink2"
end
it "ignores permalinks with characters after the index value" do
create(:enterprise, permalink: "permalink2xxx")
expect(Enterprise.find_available_permalink("permalink")).to eq "permalink2"
end
it "finds gaps in the indices of existing permalinks" do
create(:enterprise, permalink: "permalink3")
expect(Enterprise.find_available_permalink("permalink")).to eq "permalink2"
end
end
end
end

View File

@@ -0,0 +1,58 @@
require 'spec_helper'
describe ModelSet do
describe "updating" do
it "creates new models" do
attrs = {collection_attributes: {'1' => {name: 's1'},
'2' => {name: 's2'}}}
ms = ModelSet.new(Suburb, Suburb.all, attrs)
expect { ms.save }.to change(Suburb, :count).by(2)
Suburb.where(name: ['s1', 's2']).count.should == 2
end
it "updates existing models" do
e1 = create(:enterprise_group)
e2 = create(:enterprise_group)
attrs = {collection_attributes: {'1' => {id: e1.id, name: 'e1zz', description: 'foo'},
'2' => {id: e2.id, name: 'e2yy', description: 'bar'}}}
ms = ModelSet.new(EnterpriseGroup, EnterpriseGroup.all, attrs)
expect { ms.save }.to change(EnterpriseGroup, :count).by(0)
EnterpriseGroup.where(name: ['e1zz', 'e2yy']).count.should == 2
end
it "destroys deleted models" do
e1 = create(:enterprise)
e2 = create(:enterprise)
attrs = {collection_attributes: {'1' => {id: e1.id, name: 'deleteme'},
'2' => {id: e2.id, name: 'e2'}}}
ms = ModelSet.new(Enterprise, Enterprise.all, attrs, nil,
proc { |attrs| attrs['name'] == 'deleteme' })
expect { ms.save }.to change(Enterprise, :count).by(-1)
Enterprise.where(id: e1.id).should be_empty
Enterprise.where(id: e2.id).should be_present
end
it "ignores deletable new records" do
attrs = {collection_attributes: {'1' => {name: 'deleteme'}}}
ms = ModelSet.new(Enterprise, Enterprise.all, attrs, nil,
proc { |attrs| attrs['name'] == 'deleteme' })
expect { ms.save }.to change(Enterprise, :count).by(0)
end
end
end

View File

@@ -91,25 +91,25 @@ describe OrderCycle do
end
it "finds the most recently closed order cycles" do
oc1 = create(:order_cycle, orders_close_at: 2.hours.ago)
oc2 = create(:order_cycle, orders_close_at: 1.hour.ago)
oc3 = create(:order_cycle, orders_close_at: 1.hour.from_now)
oc1 = create(:simple_order_cycle, orders_close_at: 2.hours.ago)
oc2 = create(:simple_order_cycle, orders_close_at: 1.hour.ago)
oc3 = create(:simple_order_cycle, orders_close_at: 1.hour.from_now)
OrderCycle.most_recently_closed.should == [oc2, oc1]
end
it "finds the soonest opening order cycles" do
oc1 = create(:order_cycle, orders_open_at: 1.weeks.from_now)
oc2 = create(:order_cycle, orders_open_at: 2.hours.from_now)
oc3 = create(:order_cycle, orders_open_at: 1.hour.ago)
oc1 = create(:simple_order_cycle, orders_open_at: 1.weeks.from_now)
oc2 = create(:simple_order_cycle, orders_open_at: 2.hours.from_now)
oc3 = create(:simple_order_cycle, orders_open_at: 1.hour.ago)
OrderCycle.soonest_opening.should == [oc2, oc1]
end
it "finds the soonest closing order cycles" do
oc1 = create(:order_cycle, orders_close_at: 2.hours.ago)
oc2 = create(:order_cycle, orders_close_at: 2.hour.from_now)
oc3 = create(:order_cycle, orders_close_at: 1.hour.from_now)
oc1 = create(:simple_order_cycle, orders_close_at: 2.hours.ago)
oc2 = create(:simple_order_cycle, orders_close_at: 2.hour.from_now)
oc3 = create(:simple_order_cycle, orders_close_at: 1.hour.from_now)
OrderCycle.soonest_closing.should == [oc3, oc2]
end
@@ -311,7 +311,7 @@ describe OrderCycle do
end
describe "checking status" do
let(:oc) { create(:order_cycle) }
let(:oc) { create(:simple_order_cycle) }
it "reports status when an order cycle is upcoming" do
Timecop.freeze(oc.orders_open_at - 1.second) do
@@ -349,23 +349,30 @@ describe OrderCycle do
end
it "clones itself" do
oc = create(:order_cycle)
occ = oc.clone!
coordinator = create(:enterprise);
oc = create(:simple_order_cycle, coordinator_fees: [create(:enterprise_fee, enterprise: coordinator)])
ex1 = create(:exchange, order_cycle: oc)
ex2 = create(:exchange, order_cycle: oc)
oc.clone!
occ = OrderCycle.last
occ.name.should == "COPY OF #{oc.name}"
occ.orders_open_at.should be_nil
occ.orders_close_at.should be_nil
occ.coordinator.should_not be_nil
occ.coordinator.should == oc.coordinator
occ.coordinator_fee_ids.should_not be_empty
occ.coordinator_fee_ids.should == oc.coordinator_fee_ids
#(0..occ.exchanges.count).all? { |i| occ.exchanges[i].eql? oc.exchanges[i] }.should be_true
# to_h gives us a unique hash for each exchange
# check that the clone has no additional exchanges
occ.exchanges.map(&:to_h).all? do |ex|
oc.exchanges.map(&:to_h).include? ex
end
# check that the clone has original exchanges
occ.exchanges.map(&:to_h).include? ex1.to_h
occ.exchanges.map(&:to_h).include? ex2.to_h
end
describe "finding recently closed order cycles" do

View File

@@ -12,8 +12,11 @@ module Spree
let(:enterprise_any) { create(:enterprise, sells: 'any') }
let(:enterprise_own) { create(:enterprise, sells: 'own') }
let(:enterprise_none) { create(:enterprise, sells: 'none') }
let(:enterprise_any_producer) { create(:enterprise, sells: 'any', is_primary_producer: true) }
let(:enterprise_own_producer) { create(:enterprise, sells: 'own', is_primary_producer: true) }
let(:enterprise_none_producer) { create(:enterprise, sells: 'none', is_primary_producer: true) }
context "as manager of a 'any' type enterprise" do
context "as manager of an enterprise who sells 'any'" do
before do
user.enterprise_roles.create! enterprise: enterprise_any
end
@@ -23,7 +26,7 @@ module Spree
it { subject.can_manage_orders?(user).should be_true }
end
context "as manager of a 'own' type enterprise" do
context "as manager of an enterprise who sell 'own'" do
before do
user.enterprise_roles.create! enterprise: enterprise_own
end
@@ -33,16 +36,66 @@ module Spree
it { subject.can_manage_orders?(user).should be_true }
end
context "as manager of a 'none' type enterprise" do
context "as manager of an enterprise who sells 'none'" do
before do
user.enterprise_roles.create! enterprise: enterprise_none
end
it { subject.can_manage_products?(user).should be_true }
it { subject.can_manage_products?(user).should be_false }
it { subject.can_manage_enterprises?(user).should be_true }
it { subject.can_manage_orders?(user).should be_false }
end
context "as manager of a producer enterprise who sells 'any'" do
before do
user.enterprise_roles.create! enterprise: enterprise_any_producer
end
it { subject.can_manage_products?(user).should be_true }
it { subject.can_manage_enterprises?(user).should be_true }
it { subject.can_manage_orders?(user).should be_true }
end
context "as manager of a producer enterprise who sell 'own'" do
before do
user.enterprise_roles.create! enterprise: enterprise_own_producer
end
it { subject.can_manage_products?(user).should be_true }
it { subject.can_manage_enterprises?(user).should be_true }
it { subject.can_manage_orders?(user).should be_true }
end
context "as manager of a producer enterprise who sells 'none'" do
before do
user.enterprise_roles.create! enterprise: enterprise_none_producer
end
context "as a non profile" do
before do
enterprise_none_producer.is_primary_producer = true
enterprise_none_producer.producer_profile_only = false
enterprise_none_producer.save!
end
it { subject.can_manage_products?(user).should be_true }
it { subject.can_manage_enterprises?(user).should be_true }
it { subject.can_manage_orders?(user).should be_false }
end
context "as a profile" do
before do
enterprise_none_producer.is_primary_producer = true
enterprise_none_producer.producer_profile_only = true
enterprise_none_producer.save!
end
it { subject.can_manage_products?(user).should be_false }
it { subject.can_manage_enterprises?(user).should be_true }
it { subject.can_manage_orders?(user).should be_false }
end
end
context "as a new user with no enterprises" do
it { subject.can_manage_products?(user).should be_false }
it { subject.can_manage_enterprises?(user).should be_false }
@@ -70,7 +123,7 @@ module Spree
let(:er1) { create(:enterprise_relationship, parent: s1, child: d1) }
let(:er2) { create(:enterprise_relationship, parent: d1, child: s1) }
let(:er_p) { create(:enterprise_relationship, parent: s_related, child: s1, permissions_list: [:manage_products]) }
let(:er_ps) { create(:enterprise_relationship, parent: s_related, child: s1, permissions_list: [:manage_products]) }
subject { user }
let(:user) { nil }
@@ -84,7 +137,7 @@ module Spree
user
end
let(:order) {create(:order)}
let(:order) { create(:order) }
it "should be able to read/write their enterprises' products and variants" do
should have_ability([:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :destroy], for: p1)
@@ -92,7 +145,7 @@ module Spree
end
it "should be able to read/write related enterprises' products and variants with manage_products permission" do
er_p
er_ps
should have_ability([:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :destroy], for: p_related)
should have_ability([:admin, :index, :read, :edit, :update, :search, :destroy], for: p_related.master)
end
@@ -151,11 +204,19 @@ module Spree
should_not have_ability(:destroy, for: er2)
end
it "should be able to read some reports" do
should have_ability([:admin, :index, :customers, :bulk_coop, :orders_and_fulfillment, :products_and_inventory], for: :report)
end
it "should not be able to read other reports" do
should_not have_ability([:sales_total, :group_buys, :payments, :orders_and_distributors, :users_and_enterprises], for: :report)
end
end
context "when is a distributor enterprise user" do
# create distributor_enterprise1 user without full admin access
let (:user) do
let(:user) do
user = create(:user)
user.spree_roles = []
d1.enterprise_roles.build(user: user).save
@@ -178,6 +239,56 @@ module Spree
o
end
describe "editing enterprises" do
let!(:d_related) { create(:distributor_enterprise) }
let!(:er_pd) { create(:enterprise_relationship, parent: d_related, child: d1, permissions_list: [:edit_profile]) }
it "should be able to edit enterprises it manages" do
should have_ability([:read, :edit, :update, :bulk_update, :set_sells, :resend_confirmation], for: d1)
end
it "should be able to edit enterprises it has permission to" do
should have_ability([:read, :edit, :update, :bulk_update, :set_sells, :resend_confirmation], for: d_related)
end
it "should be able to manage shipping methods, payment methods and enterprise fees for enterprises it manages" do
should have_ability([:manage_shipping_methods, :manage_payment_methods, :manage_enterprise_fees], for: d1)
end
it "should not be able to manage shipping methods, payment methods and enterprise fees for enterprises it has edit profile permission to" do
should_not have_ability([:manage_shipping_methods, :manage_payment_methods, :manage_enterprise_fees], for: d_related)
end
end
describe "variant overrides" do
let(:vo1) { create(:variant_override, hub: d1, variant: p1.master) }
let(:vo2) { create(:variant_override, hub: d1, variant: p2.master) }
let(:vo3) { create(:variant_override, hub: d2, variant: p1.master) }
let(:vo4) { create(:variant_override, hub: d2, variant: p2.master) }
let!(:er1) { create(:enterprise_relationship, parent: s1, child: d1, permissions_list: [:create_variant_overrides]) }
it "should be able to access variant overrides page" do
should have_ability([:admin, :index, :bulk_update], for: VariantOverride)
end
it "should be able to read/write their own variant overrides" do
should have_ability([:admin, :index, :read, :update], for: vo1)
end
it "should not be able to read/write variant overrides when producer of product hasn't granted permission" do
should_not have_ability([:admin, :index, :read, :update], for: vo2)
end
it "should not be able to read/write variant overrides when we can't add hub to order cycle" do
should_not have_ability([:admin, :index, :read, :update], for: vo3)
end
it "should not be able to read/write other enterprises' variant overrides" do
should_not have_ability([:admin, :index, :read, :update], for: vo4)
end
end
it "should be able to read/write their enterprises' orders" do
should have_ability([:admin, :index, :read, :edit], for: o1)
end
@@ -237,9 +348,18 @@ module Spree
it "should not be able to destroy enterprise relationships for other enterprises" do
should_not have_ability(:destroy, for: er1)
end
it "should be able to read some reports" do
should have_ability([:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory], for: :report)
end
it "should not be able to read other reports" do
should_not have_ability([:sales_total, :users_and_enterprises], for: :report)
end
end
context 'Order Cycle co-ordinator, distriutor enterprise manager' do
context 'Order Cycle co-ordinator, distributor enterprise manager' do
let (:user) do
user = create(:user)
user.spree_roles = []
@@ -280,16 +400,21 @@ module Spree
end
it 'should have the ability to read and edit enterprises that I manage' do
should have_ability([:read, :edit, :update, :bulk_update], for: s1)
should have_ability([:read, :edit, :update, :bulk_update, :set_sells], for: s1)
end
it 'should not have the ability to read and edit enterprises that I do not manage' do
should_not have_ability([:read, :edit, :update, :bulk_update], for: s2)
should_not have_ability([:read, :edit, :update, :bulk_update, :set_sells], for: s2)
end
it 'should have the ability administrate and create enterpises' do
should have_ability([:admin, :index, :create], for: Enterprise)
end
it "should have the ability to search for users which share management of its enterprises" do
should have_ability([:admin, :known_users], for: :search)
should_not have_ability([:users], for: :search)
end
end
end
end

View File

@@ -9,23 +9,43 @@ describe Spree::Address do
it { should delegate(:name).to(:state).with_prefix }
end
describe "full address" do
describe "geocode address" do
let(:address) { FactoryGirl.build(:address) }
it "should include address1, address2, zipcode, city, state and country" do
address.full_address.should include(address.address1)
address.full_address.should include(address.address2)
address.full_address.should include(address.zipcode)
address.full_address.should include(address.city)
address.full_address.should include(address.state.name)
address.full_address.should include(address.country.name)
address.geocode_address.should include(address.address1)
address.geocode_address.should include(address.address2)
address.geocode_address.should include(address.zipcode)
address.geocode_address.should include(address.city)
address.geocode_address.should include(address.state.name)
address.geocode_address.should include(address.country.name)
end
it "should not include empty fields" do
address.address2 = nil
address.city = ""
address.full_address.split(',').length.should eql(4)
address.geocode_address.split(',').length.should eql(4)
end
end
describe "full address" do
let(:address) { FactoryGirl.build(:address) }
it "should include address1, address2, zipcode, city and state" do
address.full_address.should include(address.address1)
address.full_address.should include(address.address2)
address.full_address.should include(address.zipcode)
address.full_address.should include(address.city)
address.full_address.should include(address.state.name)
address.full_address.should_not include(address.country.name)
end
it "should not include empty fields" do
address.address2 = nil
address.city = ""
address.full_address.split(',').length.should eql(3)
end
end

View File

@@ -25,5 +25,27 @@ module Spree
LineItem.supplied_by_any([s1, s2]).sort.should == [li1, li2].sort
end
end
describe "calculating price with adjustments" do
it "does not return fractional cents" do
li = LineItem.new
li.stub(:price) { 55.55 }
li.stub_chain(:order, :adjustments, :where, :sum) { 11.11 }
li.stub(:quantity) { 2 }
li.price_with_adjustments.should == 61.11
end
end
describe "calculating amount with adjustments" do
it "returns a value consistent with price_with_adjustments" do
li = LineItem.new
li.stub(:price) { 55.55 }
li.stub_chain(:order, :adjustments, :where, :sum) { 11.11 }
li.stub(:quantity) { 2 }
li.amount_with_adjustments.should == 122.22
end
end
end
end

View File

@@ -48,6 +48,7 @@ module Spree
describe "attempt_cart_add" do
it "performs additional validations" do
variant = double(:variant)
variant.stub(:scope_to_hub)
quantity = 123
Spree::Variant.stub(:find).and_return(variant)

View File

@@ -27,13 +27,13 @@ describe Spree::Order do
let(:order) { build(:order, distributor: order_distributor) }
let(:pm1) { create(:payment_method, distributors: [order_distributor])}
let(:pm2) { create(:payment_method, distributors: [some_other_distributor])}
it "finds the correct payment methods" do
Spree::PaymentMethod.stub(:available).and_return [pm1, pm2]
Spree::PaymentMethod.stub(:available).and_return [pm1, pm2]
order.available_payment_methods.include?(pm2).should == false
order.available_payment_methods.include?(pm1).should == true
end
end
describe "updating the distribution charge" do
@@ -147,34 +147,42 @@ describe Spree::Order do
end
end
describe "getting the distribution charge" do
describe "getting the admin and handling charge" do
let(:o) { create(:order) }
let(:li) { create(:line_item, order: o) }
it "returns the sum of eligible enterprise fee adjustments" do
ef = create(:enterprise_fee)
ef = create(:enterprise_fee, calculator: Spree::Calculator::FlatRate.new )
ef.calculator.set_preference :amount, 123.45
a = ef.create_locked_adjustment("adjustment", li.order, li, true)
a = ef.create_locked_adjustment("adjustment", o, o, true)
o.distribution_total.should == 123.45
o.admin_and_handling_total.should == 123.45
end
it "does not include ineligible adjustments" do
ef = create(:enterprise_fee)
ef = create(:enterprise_fee, calculator: Spree::Calculator::FlatRate.new )
ef.calculator.set_preference :amount, 123.45
a = ef.create_locked_adjustment("adjustment", li.order, li, true)
a = ef.create_locked_adjustment("adjustment", o, o, true)
a.update_column :eligible, false
o.distribution_total.should == 0
o.admin_and_handling_total.should == 0
end
it "does not include adjustments that do not originate from enterprise fees" do
sm = create(:shipping_method)
sm = create(:shipping_method, calculator: Spree::Calculator::FlatRate.new )
sm.calculator.set_preference :amount, 123.45
sm.create_adjustment("adjustment", li.order, li, true)
sm.create_adjustment("adjustment", o, o, true)
o.distribution_total.should == 0
o.admin_and_handling_total.should == 0
end
it "does not include adjustments whose source is a line item" do
ef = create(:enterprise_fee, calculator: Spree::Calculator::PerItem.new )
ef.calculator.set_preference :amount, 123.45
ef.create_adjustment("adjustment", li.order, li, true)
o.admin_and_handling_total.should == 0
end
end
@@ -245,7 +253,7 @@ describe Spree::Order do
subject.should_not_receive(:empty!)
subject.set_order_cycle! subject.order_cycle
end
it "sets the order cycle when no distributor is set" do
subject.set_order_cycle! oc
subject.order_cycle.should == oc
@@ -320,15 +328,37 @@ describe Spree::Order do
end
end
describe "scopes" do
describe "scopes" do
describe "not_state" do
it "finds only orders not in specified state" do
o = FactoryGirl.create(:completed_order_with_totals)
o.cancel!
Spree::Order.not_state(:canceled).should_not include o
end
end
describe "with payment method name" do
let!(:o1) { create(:order) }
let!(:o2) { create(:order) }
let!(:pm1) { create(:payment_method, name: 'foo') }
let!(:pm2) { create(:payment_method, name: 'bar') }
let!(:p1) { create(:payment, order: o1, payment_method: pm1) }
let!(:p2) { create(:payment, order: o2, payment_method: pm2) }
it "returns the order with payment method name" do
Spree::Order.with_payment_method_name('foo').should == [o1]
end
it "doesn't return rows with a different payment method name" do
Spree::Order.with_payment_method_name('foobar').should_not include o1
Spree::Order.with_payment_method_name('foobar').should_not include o2
end
it "doesn't return duplicate rows" do
p2 = FactoryGirl.create(:payment, :order => o1, :payment_method => pm1)
Spree::Order.with_payment_method_name('foo').length.should == 1
end
end
end
describe "shipping address prepopulation" do
@@ -366,4 +396,15 @@ describe Spree::Order do
end
end
describe "sending confirmation emails" do
it "sends confirmation emails to both the user and the shop owner" do
customer_confirm_fake = double(:confirm_email_for_customer)
shop_confirm_fake = double(:confirm_email_for_shop)
expect(Spree::OrderMailer).to receive(:confirm_email_for_customer).and_return customer_confirm_fake
expect(Spree::OrderMailer).to receive(:confirm_email_for_shop).and_return shop_confirm_fake
expect(customer_confirm_fake).to receive :deliver
expect(shop_confirm_fake).to receive :deliver
create(:order).deliver_order_confirmation_email
end
end
end

View File

@@ -19,6 +19,7 @@ module Spree
it "generates a clean name for known Payment Method types" do
Spree::PaymentMethod::Check.clean_name.should == "Cash/EFT/etc. (payments for which automatic validation is not required)"
Spree::Gateway::Migs.clean_name.should == "MasterCard Internet Gateway Service (MIGS)"
Spree::Gateway::Pin.clean_name.should == "Pin Payments"
Spree::Gateway::PayPalExpress.clean_name.should == "PayPal Express"
# Testing else condition

View File

@@ -8,29 +8,18 @@ module Spree
it { should belong_to(:primary_taxon) }
it { should have_many(:product_distributions) }
end
describe "validations and defaults" do
it "is valid when created from factory" do
create(:product).should be_valid
it "is valid when built from factory" do
build(:product).should be_valid
end
it "requires a primary taxon" do
product = create(:simple_product)
product.taxons = []
product.primary_taxon = nil
product.should_not be_valid
build(:simple_product, taxons: [], primary_taxon: nil).should_not be_valid
end
it "requires a supplier" do
product = create(:simple_product)
product.supplier = nil
product.should_not be_valid
end
it "defaults available_on to now" do
Timecop.freeze
product = Product.new
product.available_on.should == Time.now
build(:simple_product, supplier: nil).should_not be_valid
end
it "does not save when master is invalid" do
@@ -41,6 +30,31 @@ module Spree
product.save.should be_false
end
it "defaults available_on to now" do
Timecop.freeze
product = Product.new
product.available_on.should == Time.now
end
describe "tax category" do
context "when a tax category is required" do
before { Spree::Config.products_require_tax_category = true }
it "is invalid when a tax category is not provided" do
build(:product, tax_category_id: nil).should_not be_valid
end
end
context "when a tax category is not required" do
before { Spree::Config.products_require_tax_category = false }
it "is valid when a tax category is not provided" do
build(:product, tax_category_id: nil).should be_valid
end
end
end
context "when the product has variants" do
let(:product) do
product = create(:simple_product)
@@ -359,8 +373,8 @@ module Spree
d2 = create(:distributor_enterprise)
p1 = create(:product)
p2 = create(:product)
oc1 = create(:order_cycle, :distributors => [d1], :variants => [p1.master])
oc2 = create(:order_cycle, :distributors => [d2], :variants => [p2.master])
oc1 = create(:simple_order_cycle, :distributors => [d1], :variants => [p1.master])
oc2 = create(:simple_order_cycle, :distributors => [d2], :variants => [p2.master])
p1.should be_in_distributor d1
p1.should_not be_in_distributor d2
@@ -371,49 +385,14 @@ module Spree
d2 = create(:distributor_enterprise)
p1 = create(:product)
p2 = create(:product)
oc1 = create(:order_cycle, :distributors => [d1], :variants => [p1.master])
oc2 = create(:order_cycle, :distributors => [d2], :variants => [p2.master])
oc1 = create(:simple_order_cycle, :distributors => [d1], :variants => [p1.master])
oc2 = create(:simple_order_cycle, :distributors => [d2], :variants => [p2.master])
p1.should be_in_order_cycle oc1
p1.should_not be_in_order_cycle oc2
end
end
describe "finding variants for an order cycle and hub" do
let(:oc) { create(:simple_order_cycle) }
let(:s) { create(:supplier_enterprise) }
let(:d1) { create(:distributor_enterprise) }
let(:d2) { create(:distributor_enterprise) }
let(:p1) { create(:simple_product) }
let(:p2) { create(:simple_product) }
let(:v1) { create(:variant, product: p1) }
let(:v2) { create(:variant, product: p2) }
let(:p_external) { create(:simple_product) }
let(:v_external) { create(:variant, product: p_external) }
let!(:ex_in) { create(:exchange, order_cycle: oc, sender: s, receiver: oc.coordinator,
incoming: true, variants: [v1, v2]) }
let!(:ex_out1) { create(:exchange, order_cycle: oc, sender: oc.coordinator, receiver: d1,
incoming: false, variants: [v1]) }
let!(:ex_out2) { create(:exchange, order_cycle: oc, sender: oc.coordinator, receiver: d2,
incoming: false, variants: [v2]) }
it "returns variants in the order cycle and distributor" do
p1.variants_for(oc, d1).should == [v1]
p2.variants_for(oc, d2).should == [v2]
end
it "does not return variants in the order cycle but not the distributor" do
p1.variants_for(oc, d2).should be_empty
p2.variants_for(oc, d1).should be_empty
end
it "does not return variants not in the order cycle" do
p_external.variants_for(oc, d1).should be_empty
end
end
describe "variant units" do
context "when the product initially has no variant unit" do

View File

@@ -1,4 +1,6 @@
describe Spree.user_class do
include AuthenticationWorkflow
describe "associations" do
it { should have_many(:owned_enterprises) }
@@ -19,9 +21,23 @@ describe Spree.user_class do
expect {
u2.owned_enterprises << e2
u2.save!
}.to raise_error ActiveRecord::RecordInvalid, "Validation failed: The nominated user is not permitted to own own any more enterprises (limit is 1)."
}.to raise_error ActiveRecord::RecordInvalid, "Validation failed: #{u2.email} is not permitted to own any more enterprises (limit is 1)."
end
end
describe "group ownership" do
let(:u1) { create(:user) }
let(:u2) { create(:user) }
let!(:g1) { create(:enterprise_group, owner: u1) }
let!(:g2) { create(:enterprise_group, owner: u1) }
let!(:g3) { create(:enterprise_group, owner: u2) }
it "provides access to owned groups" do
expect(u1.owned_groups(:reload)).to match_array([g1, g2])
expect(u2.owned_groups(:reload)).to match_array([g3])
end
end
end
context "#create" do
@@ -30,4 +46,28 @@ describe Spree.user_class do
create(:user)
end
end
describe "known_users" do
let!(:u1) { create_enterprise_user }
let!(:u2) { create_enterprise_user }
let!(:u3) { create_enterprise_user }
let!(:e1) { create(:enterprise, owner: u1, users: [u1, u2]) }
describe "as an enterprise user" do
it "returns a list of users which manage shared enterprises" do
expect(u1.known_users).to include u1, u2
expect(u1.known_users).to_not include u3
expect(u2.known_users).to include u1,u2
expect(u2.known_users).to_not include u3
expect(u3.known_users).to_not include u1,u2,u3
end
end
describe "as admin" do
let(:admin) { quick_login_as_admin }
it "returns all users" do
expect(admin.known_users).to include u1, u2, u3
end
end
end
end

View File

@@ -67,6 +67,41 @@ module Spree
end
end
describe "finding variants for an order cycle and hub" do
let(:oc) { create(:simple_order_cycle) }
let(:s) { create(:supplier_enterprise) }
let(:d1) { create(:distributor_enterprise) }
let(:d2) { create(:distributor_enterprise) }
let(:p1) { create(:simple_product) }
let(:p2) { create(:simple_product) }
let(:v1) { create(:variant, product: p1) }
let(:v2) { create(:variant, product: p2) }
let(:p_external) { create(:simple_product) }
let(:v_external) { create(:variant, product: p_external) }
let!(:ex_in) { create(:exchange, order_cycle: oc, sender: s, receiver: oc.coordinator,
incoming: true, variants: [v1, v2]) }
let!(:ex_out1) { create(:exchange, order_cycle: oc, sender: oc.coordinator, receiver: d1,
incoming: false, variants: [v1]) }
let!(:ex_out2) { create(:exchange, order_cycle: oc, sender: oc.coordinator, receiver: d2,
incoming: false, variants: [v2]) }
it "returns variants in the order cycle and distributor" do
p1.variants.for_distribution(oc, d1).should == [v1]
p2.variants.for_distribution(oc, d2).should == [v2]
end
it "does not return variants in the order cycle but not the distributor" do
p1.variants.for_distribution(oc, d2).should be_empty
p2.variants.for_distribution(oc, d1).should be_empty
end
it "does not return variants not in the order cycle" do
p_external.variants.for_distribution(oc, d1).should be_empty
end
end
end
describe "calculating the price with enterprise fees" do

View File

@@ -0,0 +1,76 @@
require 'spec_helper'
describe VariantOverride do
let(:variant) { create(:variant) }
let(:hub) { create(:distributor_enterprise) }
describe "scopes" do
let(:hub1) { create(:distributor_enterprise) }
let(:hub2) { create(:distributor_enterprise) }
let(:v) { create(:variant) }
let!(:vo1) { create(:variant_override, hub: hub1, variant: v) }
let!(:vo2) { create(:variant_override, hub: hub2, variant: v) }
it "finds variant overrides for a set of hubs" do
VariantOverride.for_hubs([hub1, hub2]).sort.should == [vo1, vo2].sort
end
end
describe "looking up prices" do
it "returns the numeric price when present" do
VariantOverride.create!(variant: variant, hub: hub, price: 12.34)
VariantOverride.price_for(hub, variant).should == 12.34
end
it "returns nil otherwise" do
VariantOverride.price_for(hub, variant).should be_nil
end
end
describe "looking up count on hand" do
it "returns the numeric stock level when present" do
VariantOverride.create!(variant: variant, hub: hub, count_on_hand: 12)
VariantOverride.count_on_hand_for(hub, variant).should == 12
end
it "returns nil otherwise" do
VariantOverride.count_on_hand_for(hub, variant).should be_nil
end
end
describe "checking if stock levels have been overriden" do
it "returns true when stock level has been overridden" do
create(:variant_override, variant: variant, hub: hub, count_on_hand: 12)
VariantOverride.stock_overridden?(hub, variant).should be_true
end
it "returns false when the override has no stock level" do
create(:variant_override, variant: variant, hub: hub, count_on_hand: nil)
VariantOverride.stock_overridden?(hub, variant).should be_false
end
it "returns false when there is no override for the hub/variant" do
VariantOverride.stock_overridden?(hub, variant).should be_false
end
end
describe "decrementing stock" do
it "decrements stock" do
vo = create(:variant_override, variant: variant, hub: hub, count_on_hand: 12)
VariantOverride.decrement_stock! hub, variant, 2
vo.reload.count_on_hand.should == 10
end
it "silently logs an error if the variant override doesn't have a stock level" do
vo = create(:variant_override, variant: variant, hub: hub, count_on_hand: nil)
Bugsnag.should_receive(:notify)
VariantOverride.decrement_stock! hub, variant, 2
vo.reload.count_on_hand.should be_nil
end
it "silently logs an error if the variant override does not exist" do
Bugsnag.should_receive(:notify)
VariantOverride.decrement_stock! hub, variant, 2
end
end
end

View File

@@ -4,7 +4,7 @@ describe "Shop API" do
include ShopWorkflow
describe "filtering products" do
let(:distributor) { create(:distributor_enterprise) }
let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let(:supplier) { create(:supplier_enterprise) }
let(:oc1) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 2.days.from_now) }
let(:p1) { create(:simple_product, on_demand: false) }

View File

@@ -0,0 +1,15 @@
describe Api::Admin::VariantOverrideSerializer do
let(:variant) { create(:variant) }
let(:hub) { create(:distributor_enterprise) }
let(:price) { 77.77 }
let(:count_on_hand) { 11111 }
let(:variant_override) { create(:variant_override, variant: variant, hub: hub, price: price, count_on_hand: count_on_hand) }
it "serializes a variant override" do
serializer = Api::Admin::VariantOverrideSerializer.new variant_override
serializer.to_json.should match variant.id.to_s
serializer.to_json.should match hub.id.to_s
serializer.to_json.should match price.to_s
serializer.to_json.should match count_on_hand.to_s
end
end

View File

@@ -18,22 +18,4 @@ describe Api::EnterpriseSerializer do
serializer = Api::EnterpriseSerializer.new enterprise
serializer.to_json.should match "map_005-hub.svg"
end
describe "visibility" do
before do
enterprise.stub(:visible).and_return true
end
it "is visible when confirmed" do
enterprise.stub(:confirmed?).and_return true
serializer = Api::EnterpriseSerializer.new enterprise
expect(serializer.to_json).to match "\"visible\":true"
end
it "is not visible when unconfirmed" do
enterprise.stub(:confirmed?).and_return false
serializer = Api::EnterpriseSerializer.new enterprise
expect(serializer.to_json).to match "\"visible\":false"
end
end
end

View File

@@ -0,0 +1,14 @@
describe Api::ProductSerializer do
let(:hub) { create(:distributor_enterprise) }
let(:oc) { create(:simple_order_cycle, distributors: [hub], variants: [v1]) }
let(:p) { create(:simple_product) }
let!(:v1) { create(:variant, product: p, unit_value: 3) }
let!(:v2) { create(:variant, product: p, unit_value: 5) }
it "scopes variants to distribution" do
s = Api::ProductSerializer.new p, current_distributor: hub, current_order_cycle: oc
json = s.to_json
json.should include v1.options_text
json.should_not include v2.options_text
end
end

View File

@@ -28,10 +28,6 @@ require 'spree/api/testing_support/helpers'
require 'spree/api/testing_support/helpers_decorator'
require 'spree/core/testing_support/authorization_helpers'
require 'active_record/fixtures'
fixtures_dir = File.expand_path('../../db/default', __FILE__)
ActiveRecord::Fixtures.create_fixtures(fixtures_dir, ['spree/states', 'spree/countries'])
# Capybara config
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist

View File

@@ -0,0 +1,56 @@
RSpec::Matchers.define :have_select2 do |id, options={}|
# TODO: Implement other have_select options
# http://www.rubydoc.info/github/jnicklas/capybara/Capybara/Node/Matchers#has_select%3F-instance_method
# TODO: Instead of passing in id, use a more general locator
match_for_should do |node|
@id, @options, @node = id, options, node
#id = find_label_by_text(locator)
from = "#s2id_#{id}"
results = []
results << node.has_selector?(from)
if results.all?
results << all_options_present(from, options[:with_options]) if options.key? :with_options
results << exact_options_present(from, options[:options]) if options.key? :options
end
results.all?
end
failure_message_for_should do |actual|
message = "expected to find select2 ##{@id}"
message += " with #{@options.inspect}" if @options.any?
message
end
match_for_should_not do |node|
raise "Not yet implemented"
end
def all_options_present(from, options)
with_select2_open(from) do
options.all? do |option|
@node.has_selector? "div.select2-drop-active ul.select2-results li", text: option
end
end
end
def exact_options_present(from, options)
with_select2_open(from) do
@node.all("div.select2-drop-active ul.select2-results li").map(&:text) == options
end
end
def with_select2_open(from)
find(from).click
r = yield
find(from).click
r
end
end

View File

@@ -1,6 +1,7 @@
module ShopWorkflow
def add_to_cart
first("input.add_to_cart").click
wait_until_enabled 'input.add_to_cart'
first("input.add_to_cart:not([disabled='disabled'])").click
end
def have_price(price)

View File

@@ -11,11 +11,21 @@ module WebHelper
# use_short_wait
# ...
# end
def use_short_wait
around { |example| Capybara.using_wait_time(2) { example.run } }
def use_short_wait(seconds=2)
around { |example| Capybara.using_wait_time(seconds) { example.run } }
end
end
def have_input(name, opts={})
selector = "[name='#{name}']"
selector += "[placeholder='#{opts[:placeholder]}']" if opts.key? :placeholder
element = page.all(selector).first
element.value.should == opts[:with] if element && opts.key?(:with)
have_selector selector
end
def current_path_should_be path
current_path = URI.parse(current_url).path
@@ -115,20 +125,25 @@ module WebHelper
# http://www.elabs.se/blog/53-why-wait_until-was-removed-from-capybara
# Do not use this without good reason. Capybara's built-in waiting is very effective.
def wait_until
def wait_until(secs=nil)
require "timeout"
Timeout.timeout(Capybara.default_wait_time) do
Timeout.timeout(secs || Capybara.default_wait_time) do
sleep(0.1) until value = yield
value
end
end
def wait_until_enabled(selector)
wait_until(10) { first("#{selector}:not([disabled='disabled'])") }
end
def select2_select(value, options)
id = options[:from]
options[:from] = "#s2id_#{id}"
targetted_select2(value, options)
end
# Deprecated: Use have_select2 instead (spec/support/matchers/select2_matchers.rb)
def have_select2_option(value, options)
container = options[:dropdown_css] || ".select2-with-searchbox"
page.execute_script %Q{$('#{options[:from]}').select2('open')}

18
spec/support/seeds.rb Normal file
View File

@@ -0,0 +1,18 @@
# Minimal test seeding
# --------------------
#
# Countries and states are seeded once in the beginning. The database cleaner
# leaves them there when deleting the rest (see spec/spec_helper.rb).
# You can add more entries here if you need them for your tests.
if Spree::Country.scoped.empty?
Spree::Country.create!({"name"=>"Australia", "iso3"=>"AUS", "iso"=>"AU", "iso_name"=>"AUSTRALIA", "numcode"=>"36"}, :without_protection => true)
country = Spree::Country.find_by_name('Australia')
Spree::State.create!({"name"=>"Victoria", "abbr"=>"Vic", :country=>country}, :without_protection => true)
Spree::State.create!({"name"=>"New South Wales", "abbr"=>"NSW", :country=>country}, :without_protection => true)
end
# Since the country seeding differs from other environments, the default
# country id has to be updated here. This line can be removed as soon as the
# default country id is replaced by something database independent.
Spree::Config.default_country_id = Spree::Country.find_by_name('Australia').id