Merge branch 'master' into product-amount-units

Conflicts:
	app/assets/javascripts/admin/bulk_product_update.js.coffee
	spec/spec_helper.rb
This commit is contained in:
Rohan Mitchell
2014-01-14 15:34:05 +11:00
88 changed files with 1723 additions and 719 deletions

View File

@@ -0,0 +1,122 @@
require 'spec_helper'
describe ShopController do
let(:d) { create(:distributor_enterprise) }
it "redirects to the home page if no distributor is selected" do
spree_get :show
response.should redirect_to root_path
end
describe "with a distributor in place" do
before do
controller.stub(:current_distributor).and_return d
end
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])
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])
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])
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
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])
spree_post :order_cycle, order_cycle_id: oc2.id
response.should be_success
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])
controller.stub(:current_order_cycle).and_return oc1
spree_get :order_cycle
response.body.should have_content oc1.id
end
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)])
spree_post :order_cycle, order_cycle_id: oc3.id
response.status.should == 404
controller.current_order_cycle.should == nil
end
end
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)) }
before do
exchange = Exchange.find(order_cycle.exchanges.to_enterprises(d).outgoing.first.id)
exchange.variants << product.master
end
it "builds a list of producers/suppliers" do
spree_get :show
assigns[:producers].should == [supplier]
end
end
describe "returning products" do
let(:product) { create(:product) }
let(:order_cycle) { create(:order_cycle, distributors: [d], coordinator: create(:distributor_enterprise)) }
before do
exchange = Exchange.find(order_cycle.exchanges.to_enterprises(d).outgoing.first.id)
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
context "RABL tests" do
render_views
it "only returns products for the current order cycle" do
controller.stub(:current_order_cycle).and_return order_cycle
xhr :get, :products
response.body.should have_content product.name
end
end
end
end
end

View File

@@ -168,7 +168,7 @@ describe Spree::Admin::ReportsController do
it "should build distributors for the current user" do
spree_get :products_and_inventory
assigns(:distributors).should == [d1, d2, d3]
assigns(:distributors).sort.should == [d1, d2, d3].sort
end
it "builds suppliers for the current user" do

View File

@@ -1,10 +1,6 @@
require 'spec_helper'
describe Spree::OrdersController do
def current_user
controller.current_user
end
it "selects distributors" do
d = create(:distributor_enterprise)
p = create(:product, :distributors => [d])
@@ -31,83 +27,18 @@ describe Spree::OrdersController do
order.distributor.should be_nil
end
describe "adding a product to the cart with a distribution combination that can't service the existing cart" do
before do
@request.env["HTTP_REFERER"] = 'http://test.host/'
end
it "errors when an invalid distributor is selected" do
# Given a product and some distributors
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
p = create(:product, :price => 12.34)
oc = create(:simple_order_cycle, :distributors => [d1], :variants => [p.master])
# When I attempt to add the product to the cart with an invalid distributor, it should not be added
expect do
spree_post :populate, variants: {p.master.id => 1}, distributor_id: d2.id, order_cycle_id: oc.id
response.should redirect_to :back
end.to change(self, :num_items_in_cart).by(0)
# And I should see an error
flash[:error].should == "That product is not available from the chosen distributor or order cycle."
end
it "errors when an invalid order cycle is selected" do
# Given a product and some order cycles
d = create(:distributor_enterprise)
p = create(:product, :price => 12.34)
oc1 = create(:simple_order_cycle, :distributors => [d], :variants => [p.master])
oc2 = create(:simple_order_cycle, :distributors => [d], :variants => [])
# When I attempt to add the product to my cart with an invalid order cycle, it should not be added
expect do
spree_post :populate, variants: {p.master.id => 1}, distributor_id: d.id, order_cycle_id: oc2.id
response.should redirect_to :back
end.to change(self, :num_items_in_cart).by(0)
# And I should see an error
flash[:error].should == "That product is not available from the chosen distributor or order cycle."
end
it "errors when distribution is valid for the new product but does not cover the cart" do
# Given two products with different distributors
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
p1 = create(:product, :price => 12.34)
p2 = create(:product, :price => 23.45)
oc1 = create(:simple_order_cycle, :distributors => [d1], :variants => [p1.master])
oc2 = create(:simple_order_cycle, :distributors => [d2], :variants => [p2.master])
# When I add the first to my cart
expect do
spree_post :populate, variants: {p1.master.id => 1}, distributor_id: d1.id, order_cycle_id: oc1.id
response.should redirect_to spree.cart_path
end.to change(self, :num_items_in_cart).by(1)
# And I attempt to add the second, then the product should not be added to my cart
expect do
spree_post :populate, variants: {p2.master.id => 1}, distributor_id: d2.id, order_cycle_id: oc2.id
response.should redirect_to :back
end.to change(self, :num_items_in_cart).by(0)
# And I should see an error
flash[:error].should == "That distributor or order cycle can't supply all the products in your cart. Please choose another."
end
end
context "adding a group buy product to the cart" do
it "sets a variant attribute for the max quantity" do
distributor_product = create(:distributor_enterprise)
p = create(:product, :distributors => [distributor_product], :group_buy => true)
order = subject.current_order(true)
order.stub(:distributor) { distributor_product }
order.should_receive(:set_variant_attributes).with(p.master, {'max_quantity' => '3'})
controller.stub(:current_order).and_return(order)
expect do
spree_post :populate, :variants => {p.master.id => 1}, :variant_attributes => {p.master.id => {:max_quantity => 3}}, :distributor_id => distributor_product.id
spree_post :populate, :variants => {p.master.id => 1}, :variant_attributes => {p.master.id => {:max_quantity => 3}}
end.to change(Spree::LineItem, :count).by(1)
end
end
@@ -141,6 +72,7 @@ describe Spree::OrdersController do
end
end
private
def num_items_in_cart

View File

@@ -21,14 +21,45 @@ feature %q{
login_to_admin_section
end
it "displays a 'loading' splash for products" do
FactoryGirl.create(:simple_product)
visit '/admin/products/bulk_edit'
page.should have_selector "div.loading", :text => "Loading Products..."
end
it "displays a list of products" do
p1 = FactoryGirl.create(:product)
p2 = FactoryGirl.create(:product)
visit '/admin/products/bulk_edit'
page.should have_field "product_name", with: p1.name
page.should have_field "product_name", with: p2.name
page.should have_field "product_name", with: p1.name, :visible => true
page.should have_field "product_name", with: p2.name, :visible => true
end
it "displays a message when number of products is zero" do
visit '/admin/products/bulk_edit'
page.should have_text "No matching products found."
end
pending "displays a message when number of products is too great" do
501.times { FactoryGirl.create(:simple_product) }
visit '/admin/products/bulk_edit'
page.should have_text "Search returned too many products to display (500+), please apply more search filters to reduce the number of matching products"
end
it "displays pagination information" do
p1 = FactoryGirl.create(:product)
p2 = FactoryGirl.create(:product)
visit '/admin/products/bulk_edit'
page.should have_text "Displaying 1-2 of 2 products"
end
it "displays a select box for suppliers, with the appropriate supplier selected" do
@@ -209,6 +240,9 @@ feature %q{
login_to_admin_section
visit '/admin/products/bulk_edit'
first("div.option_tab_titles h6", :text => "Toggle Columns").click
first("li.column-list-item", text: "Available On").click
page.should have_field "product_name", with: p.name
page.should have_select "supplier", selected: s1.name
@@ -342,6 +376,53 @@ feature %q{
page.find("span#update-status-message").should have_content "Update complete"
end
scenario "updating a product after cloning a product" do
FactoryGirl.create(:product, :name => "product 1")
login_to_admin_section
visit '/admin/products/bulk_edit'
first("a.clone-product").click
fill_in "product_name", :with => "new product name"
click_button 'Update'
page.find("span#update-status-message").should have_content "Update complete"
end
scenario "updating when no changes have been made" do
Capybara.default_wait_time = 2
FactoryGirl.create(:product, :name => "product 1")
FactoryGirl.create(:product, :name => "product 2")
login_to_admin_section
visit '/admin/products/bulk_edit'
click_button 'Update'
page.find("span#update-status-message").should have_content "No changes to update."
Capybara.default_wait_time = 5
end
scenario "updating when a filter has been applied" do
p1 = FactoryGirl.create(:simple_product, :name => "product1")
p2 = FactoryGirl.create(:simple_product, :name => "product2")
login_to_admin_section
visit '/admin/products/bulk_edit'
first("div.option_tab_titles h6", :text => "Filter Products").click
select "Name", :from => "filter_property"
select "Contains", :from => "filter_predicate"
fill_in "filter_value", :with => "1"
click_button "Apply Filter"
page.should_not have_field "product_name", with: p2.name
fill_in "product_name", :with => "new product1"
click_on 'Update'
page.find("span#update-status-message").should have_content "Update complete"
end
scenario "updating a product when there are more products than the default API page size" do
26.times { FactoryGirl.create(:simple_product) }
login_to_admin_section
@@ -447,7 +528,6 @@ feature %q{
page.should have_selector "a.clone-product", :count => 3
first("a.clone-product").click
page.should have_selector "a.clone-product", :count => 4
page.should have_field "product_name", with: "COPY OF #{p1.name}"
page.should have_select "supplier", selected: "#{p1.supplier.name}"
@@ -462,24 +542,61 @@ feature %q{
end
describe "using the page" do
describe "using column display toggle" do
describe "using tabs to hide and display page controls" do
it "shows a column display toggle button, which shows a list of columns when clicked" do
FactoryGirl.create(:simple_product)
login_to_admin_section
visit '/admin/products/bulk_edit'
page.should have_selector "div.column_toggle", :visible => false
page.should have_selector "div.option_tab_titles h6.unselected", :text => "Toggle Columns"
first("div.option_tab_titles h6", :text => "Toggle Columns").click
page.should have_selector "div.option_tab_titles h6.selected", :text => "Toggle Columns"
page.should have_selector "div.column_toggle", :visible => true
page.should have_selector "li.column-list-item", text: "Available On"
page.should have_selector "div.filters", :visible => false
page.should have_selector "div.option_tab_titles h6.unselected", :text => "Filter Products"
first("div.option_tab_titles h6", :text => "Filter Products").click
page.should have_selector "div.option_tab_titles h6.unselected", :text => "Toggle Columns"
page.should have_selector "div.option_tab_titles h6.selected", :text => "Filter Products"
page.should have_selector "div.filters", :visible => true
page.should have_selector "li.column-list-item", text: "Available On"
first("div.option_tab_titles h6", :text => "Filter Products").click
page.should have_selector "div.option_tab_titles h6.unselected", :text => "Filter Products"
page.should have_selector "div.option_tab_titles h6.unselected", :text => "Toggle Columns"
page.should have_selector "div.filters", :visible => false
page.should have_selector "div.column_toggle", :visible => false
end
end
describe "using column display toggle" do
it "shows a column display toggle button, which shows a list of columns when clicked" do
FactoryGirl.create(:simple_product)
login_to_admin_section
visit '/admin/products/bulk_edit'
first("div.option_tab_titles h6", :text => "Toggle Columns").click
first("li.column-list-item", text: "Available On").click
page.should have_selector "th", :text => "NAME"
page.should have_selector "th", :text => "SUPPLIER"
page.should have_selector "th", :text => "PRICE"
page.should have_selector "th", :text => "ON HAND"
page.should have_selector "th", :text => "AV. ON"
page.should have_button "Toggle Columns"
click_button "Toggle Columns"
page.should have_selector "div.option_tab_titles h6", :text => "Toggle Columns"
page.should have_selector "div ul.column-list li.column-list-item", text: "Supplier"
all("div ul.column-list li.column-list-item").select{ |e| e.text == "Supplier" }.first.click
first("li.column-list-item", text: "Supplier").click
page.should_not have_selector "th", :text => "SUPPLIER"
page.should have_selector "th", :text => "NAME"
@@ -488,6 +605,147 @@ feature %q{
page.should have_selector "th", :text => "AV. ON"
end
end
describe "using pagination controls" do
it "shows pagination controls" do
27.times { FactoryGirl.create(:product) }
login_to_admin_section
visit '/admin/products/bulk_edit'
page.should have_select 'perPage', :selected => '25'
within '.pagination' do
page.should have_text "1 2"
page.should have_text "Next"
page.should have_text "Last"
end
end
it "allows the number of visible products to be altered" do
27.times { FactoryGirl.create(:product) }
login_to_admin_section
visit '/admin/products/bulk_edit'
select '25', :from => 'perPage'
page.all("input[name='product_name']").select{ |e| e.visible? }.length.should == 25
select '50', :from => 'perPage'
page.all("input[name='product_name']").select{ |e| e.visible? }.length.should == 27
end
it "displays the correct products when changing pages" do
25.times { FactoryGirl.create(:product, :name => "page1product") }
5.times { FactoryGirl.create(:product, :name => "page2product") }
login_to_admin_section
visit '/admin/products/bulk_edit'
select '25', :from => 'perPage'
page.all("input[name='product_name']").select{ |e| e.visible? }.all?{ |e| e.value == "page1product" }.should == true
click_link "2"
page.all("input[name='product_name']").select{ |e| e.visible? }.all?{ |e| e.value == "page2product" }.should == true
end
it "moves the user to the last available page when changing the number of pages in any way causes user to become orphaned" do
50.times { FactoryGirl.create(:product) }
FactoryGirl.create(:product, :name => "fancy_product_name")
login_to_admin_section
visit '/admin/products/bulk_edit'
select '25', :from => 'perPage'
click_link "3"
select '50', :from => 'perPage'
page.first("div.pagenav span.page.current").should have_text "2"
page.all("input[name='product_name']", :visible => true).length.should == 1
select '25', :from => 'perPage'
fill_in "quick_filter", :with => "fancy_product_name"
page.first("div.pagenav span.page.current").should have_text "1"
page.all("input[name='product_name']", :visible => true).length.should == 1
end
it "paginates the filtered product list rather than all products" do
25.times { FactoryGirl.create(:product, :name => "product_name") }
3.times { FactoryGirl.create(:product, :name => "test_product_name") }
login_to_admin_section
visit '/admin/products/bulk_edit'
select '25', :from => 'perPage'
page.should have_text "1 2"
fill_in "quick_filter", :with => "test_product_name"
page.all("input[name='product_name']", :visible => true).length.should == 3
page.all("input[name='product_name']", :visible => true).all?{ |e| e.value == "test_product_name" }.should == true
page.should_not have_text "1 2"
page.should have_text "1"
end
end
describe "using filtering controls" do
it "displays basic filtering controls" do
FactoryGirl.create(:simple_product)
login_to_admin_section
visit '/admin/products/bulk_edit'
page.should have_selector "div.option_tab_titles h6", :text => "Filter Products"
first("div.option_tab_titles h6", :text => "Filter Products").click
page.should have_select "filter_property", :with_options => ["Supplier", "Name"]
page.should have_select "filter_predicate", :with_options => ["Equals", "Contains"]
page.should have_field "filter_value"
end
describe "clicking the 'Apply Filter' Button" do
before(:each) do
FactoryGirl.create(:simple_product, :name => "Product1")
FactoryGirl.create(:simple_product, :name => "Product2")
login_to_admin_section
visit '/admin/products/bulk_edit'
first("div.option_tab_titles h6", :text => "Filter Products").click
select "Name", :from => "filter_property"
select "Equals", :from => "filter_predicate"
fill_in "filter_value", :with => "Product1"
click_button "Apply Filter"
end
it "adds a new filter to the list of applied filters" do
page.should have_text "Name Equals Product1"
end
it "displays the 'loading' splash" do
page.should have_selector "div.loading", :text => "Loading Products..."
end
it "loads appropriate products" do
page.should have_field "product_name", :with => "Product1"
page.should_not have_field "product_name", :with => "Product2"
end
describe "clicking the 'Remove Filter' link" do
before(:each) do
click_link "Remove Filter"
end
it "removes the filter from the list of applied filters" do
page.should_not have_text "Name Equals Product1"
end
it "displays the 'loading' splash" do
page.should have_selector "div.loading", :text => "Loading Products..."
end
it "loads appropriate products" do
page.should have_field "product_name", :with => "Product1"
page.should have_field "product_name", :with => "Product2"
end
end
end
end
end
context "as an enterprise manager" do
@@ -535,6 +793,9 @@ feature %q{
p = product_supplied
visit '/admin/products/bulk_edit'
first("div.option_tab_titles h6", :text => "Toggle Columns").click
first("li.column-list-item", text: "Available On").click
page.should have_field "product_name", with: p.name
page.should have_select "supplier", selected: s1.name

View File

@@ -379,8 +379,8 @@ feature %q{
# Then my times should have been saved
flash_message.should == 'Order cycles have been updated.'
OrderCycle.all.map { |oc| oc.orders_open_at.sec }.should == [0, 2, 4]
OrderCycle.all.map { |oc| oc.orders_close_at.sec }.should == [1, 3, 5]
OrderCycle.order('id ASC').map { |oc| oc.orders_open_at.sec }.should == [0, 2, 4]
OrderCycle.order('id ASC').map { |oc| oc.orders_close_at.sec }.should == [1, 3, 5]
end
scenario "cloning an order cycle" do

View File

@@ -30,7 +30,7 @@ feature 'shipping methods' do
sm = Spree::ShippingMethod.last
sm.name.should == 'Carrier Pidgeon'
sm.distributors.should == [d1, d2]
sm.distributors.sort.should == [d1, d2].sort
end
it "at checkout, user can only see shipping methods for their current distributor (checkout spec)"

View File

@@ -21,123 +21,13 @@ feature %q{
click_button 'Add To Cart'
# Then I should see an error message
page.should have_content "Please choose a distributor for this order."
page.should have_content "That product is not available from the chosen distributor or order cycle"
# And the product should not have been added to my cart
Spree::Order.last.line_items.should be_empty
end
scenario "adding the first product to the cart", :future => true do
# Given a product, some distributors and a defined shipping cost
d1 = create(:distributor_enterprise, :name => "Green Grass")
d2 = create(:distributor_enterprise, :name => "AusFarmers United")
create(:product, :distributors => [d2])
p = create(:product, :price => 12.34)
create(:product_distribution, :product => p, :distributor => d1)
# ... with a flat rate distribution fee of $1.23
ef = p.product_distributions.first.enterprise_fee
ef.calculator = Spree::Calculator::FlatRate.new preferred_amount: 1.23
ef.calculator.save!
# When I choose a distributor
visit spree.root_path
click_on "AusFarmers United"
# And I add an item to my cart from a different distributor
visit spree.product_path p
select(d1.name, :from => 'distributor_id')
click_button 'Add To Cart'
# Then the correct totals should be displayed
page.should have_selector 'span.item-total', :text => '$12.34'
page.should have_selector 'span.distribution-total', :text => '$1.23'
page.should have_selector 'span.grand-total', :text => '$13.57'
# And the item should be in my cart
order = Spree::Order.last
line_item = order.line_items.first
line_item.product.should == p
# And my order should have its distributor set to the chosen distributor
order.distributor.should == d1
end
context "adding a subsequent product to the cart" do
it "when there are several valid distributors, allows a choice from these options" do
# Given two products, both distributed by two distributors
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
p1 = create(:product, :distributors => [d1, d2])
p2 = create(:product, :distributors => [d1, d2])
# When I add the first to my cart via d1
visit spree.product_path p1
select d1.name, :from => 'distributor_id'
click_button 'Add To Cart'
# And I go to add the second, I should have a choice of distributor
visit spree.product_path p2
page.should have_selector '#distributor_id option', :text => d1.name
page.should have_selector '#distributor_id option', :text => d2.name
# When I add the second, both should be in my cart, and my distributor should be the one chosen second
select d2.name, :from => 'distributor_id'
click_button 'Add To Cart'
visit spree.cart_path
page.should have_selector 'h4 a', :text => p1.name
page.should have_selector 'h4 a', :text => p2.name
page.should have_selector "#logo h1 a", :text => d2.name
end
it "when the only valid distributor is the chosen one, does not allow the user to choose a distributor" do
# Given two products, each at the same distributor
d = create(:distributor_enterprise)
p1 = create(:product, :distributors => [d])
p2 = create(:product, :distributors => [d])
# When I add the first to my cart
visit spree.product_path p1
select d.name, :from => 'distributor_id'
click_button 'Add To Cart'
# And I go to add the second, I should not have a choice of distributor
visit spree.product_path p2
page.should_not have_selector 'select#distributor_id'
page.should have_selector '.distributor-fixed', :text => "Your distributor for this order is #{d.name}"
# When I add the second, both should be in my cart
click_button 'Add To Cart'
visit spree.cart_path
page.should have_selector 'h4 a', :text => p1.name
page.should have_selector 'h4 a', :text => p2.name
end
it "when the only valid distributor differs from the chosen one, alerts the user and changes distributor on add to cart" do
# Given two products, one available at only one distributor
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
p1 = create(:product, :distributors => [d1, d2])
p2 = create(:product, :distributors => [d2])
# When I add the first to my cart
visit spree.product_path p1
select d1.name, from: 'distributor_id'
click_button 'Add To Cart'
# And I go to add the second
visit spree.product_path p2
# Then I should see a message offering to change distributor for my order
page.should have_content "Your distributor for this order will be changed to #{d2.name} if you add this product to your cart."
# When I add the second to my cart
click_button 'Add To Cart'
# Then My distributor should have changed
page.should have_selector "#logo h1 a", :text => d2.name
end
it "does not allow the user to add a product from a distributor that cannot supply the cart's products" do
# Given two products, each at a different distributor
d1 = create(:distributor_enterprise)
@@ -146,8 +36,8 @@ feature %q{
p2 = create(:product, :distributors => [d2])
# When I add one of them to my cart
select_distribution d1
visit spree.product_path p1
select d1.name, :from => 'distributor_id'
click_button 'Add To Cart'
# And I attempt to add the other
@@ -205,7 +95,7 @@ feature %q{
click_button 'Add To Cart'
# Then I should see an error message
page.should have_content "Please choose a distributor and order cycle for this order."
page.should have_content "Please choose an order cycle for this order."
# And the product should not have been added to my cart
Spree::Order.last.line_items.should be_empty
@@ -218,9 +108,8 @@ feature %q{
oc = create(:simple_order_cycle, :distributors => [d], :variants => [p.master])
# When I add an item to my cart
select_distribution d, oc
visit spree.product_path p
select d.name, :from => 'distributor_id'
select oc.name, :from => 'order_cycle_id'
click_button 'Add To Cart'
# Then the correct totals should be displayed
@@ -239,144 +128,6 @@ feature %q{
order.distributor.should == d
order.order_cycle.should == oc
end
scenario "adding a product to the cart with an invalid distribution combination" do
# Given a product and some distributors
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
p = create(:product, :price => 12.34)
oc1 = create(:simple_order_cycle, :distributors => [d1], :variants => [p.master])
oc2 = create(:simple_order_cycle, :distributors => [d2], :variants => [p.master])
# When I attempt to add the product to my cart with an invalid distribution
visit spree.product_path p
select d1.name, :from => 'distributor_id'
select oc2.name, :from => 'order_cycle_id'
click_button 'Add To Cart'
# Then I should see an error message
page.should have_content "That product is not available from the chosen distributor or order cycle."
# And the product should not be in my cart
Spree::Order.last.line_items.should be_empty
end
context "adding a subsequent product to the cart" do
it "when there are several valid order cycles, allows a choice from these options" do
# Given two products, both distributed by two distributors
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
p1 = create(:product)
p2 = create(:product)
oc1 = create(:simple_order_cycle,
:distributors => [d1, d2], :variants => [p1.master, p2.master])
oc2 = create(:simple_order_cycle,
:distributors => [d1, d2], :variants => [p1.master, p2.master])
# When I add the first to my cart via d1/oc1
visit spree.product_path p1
select d1.name, :from => 'distributor_id'
select oc1.name, :from => 'order_cycle_id'
click_button 'Add To Cart'
# And I go to add the second, I should have a choice of order cycle and distributor
visit spree.product_path p2
page.should have_selector '#distributor_id option', :text => d1.name
page.should have_selector '#distributor_id option', :text => d2.name
page.should have_selector '#order_cycle_id option', :text => oc1.name
page.should have_selector '#order_cycle_id option', :text => oc2.name
# When I add the second, both should be in my cart, and my
# distributor and order cycle should be the one chosen second
select d2.name, :from => 'distributor_id'
select oc2.name, :from => 'order_cycle_id'
click_button 'Add To Cart'
visit spree.cart_path
page.should have_selector 'h4 a', :text => p1.name
page.should have_selector 'h4 a', :text => p2.name
page.should have_selector "#logo h1 a", :text => d2.name
end
it "when the only valid order cycle is the chosen one, does not allow the user to choose an order cycle" do
# Given two products, each at the same distributor
d = create(:distributor_enterprise)
p1 = create(:product)
p2 = create(:product)
oc = create(:simple_order_cycle, :distributors => [d],
:variants => [p1.master, p2.master])
# When I add the first to my cart
visit spree.product_path p1
select d.name, :from => 'distributor_id'
select oc.name, :from => 'order_cycle_id'
click_button 'Add To Cart'
# And I go to add the second, I should not have a choice of distributor or order cycle
visit spree.product_path p2
page.should_not have_selector 'select#distributor_id'
page.should have_selector '.distributor-fixed', :text => "Your distributor for this order is #{d.name}"
page.should_not have_selector 'select#order_cycle_id'
page.should have_selector '.order-cycle-fixed', :text => "Your order cycle for this order is #{oc.name}"
# When I add the second, both should be in my cart
click_button 'Add To Cart'
visit spree.cart_path
page.should have_selector 'h4 a', :text => p1.name
page.should have_selector 'h4 a', :text => p2.name
end
it "when the only valid distributor differs from the chosen one, alerts the user and changes distributor on add to cart" do
# Given two products, one available at only one distributor
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
p1 = create(:product)
p2 = create(:product)
oc1 = create(:simple_order_cycle, :distributors => [d1], :variants => [p1.master])
oc2 = create(:simple_order_cycle, :distributors => [d2], :variants => [p1.master, p2.master])
# When I add the first to my cart
visit spree.product_path p1
select d1.name, from: 'distributor_id'
select oc1.name, from: 'order_cycle_id'
click_button 'Add To Cart'
# And I go to add the second
visit spree.product_path p2
# Then I should see a message offering to change distributor for my order
page.should have_content "Your distributor for this order will be changed to #{d2.name} if you add this product to your cart."
# When I add the second to my cart
click_button 'Add To Cart'
# Then my distributor should have changed
page.should have_selector "#logo h1 a", :text => d2.name
end
it "does not allow the user to add a product from an order cycle that cannot supply the cart's products" do
# Given two products, each at a different order cycle
d = create(:distributor_enterprise)
p1 = create(:product)
p2 = create(:product)
oc1 = create(:simple_order_cycle, :distributors => [d], :variants => [p1.master])
oc2 = create(:simple_order_cycle, :distributors => [d], :variants => [p2.master])
# When I add one of them to my cart
visit spree.product_path p1
select d.name, :from => 'distributor_id'
select oc1.name, :from => 'order_cycle_id'
click_button 'Add To Cart'
# And I attempt to add the other
visit spree.product_path p2
# Then I should not be allowed to add the product
page.should_not have_selector "button#add-to-cart-button"
page.should have_content "Please complete your order from #{oc1.name} before shopping in a different order cycle."
end
end
end
context "group buys" do
@@ -386,8 +137,8 @@ feature %q{
p = create(:product, :distributors => [d], :group_buy => true)
# When I add the item to my cart
select_distribution d
visit spree.product_path p
select d.name, :from => 'distributor_id'
fill_in "variants_#{p.master.id}", :with => 2
fill_in "variant_attributes_#{p.master.id}_max_quantity", :with => 3
click_button 'Add To Cart'
@@ -407,8 +158,8 @@ feature %q{
create(:variant, :product => p)
# When I add the item to my cart
select_distribution d
visit spree.product_path p
select d.name, :from => 'distributor_id'
fill_in "quantity", :with => 2
fill_in "max_quantity", :with => 3
click_button 'Add To Cart'
@@ -438,8 +189,8 @@ feature %q{
p = create(:product, :distributors => [d], :group_buy => true)
# When I add the item to my cart
select_distribution d
visit spree.product_path p
select d.name, :from => 'distributor_id'
fill_in "variants_#{p.master.id}", :with => 2
fill_in "variant_attributes_#{p.master.id}_max_quantity", :with => 1
click_button 'Add To Cart'

View File

@@ -90,79 +90,5 @@ feature %q{
page.all('#product-variants li input').count.should == 1
end
end
context "viewing a product, it provides a choice of distributor when adding to cart" do
it "works when no distributor is chosen" do
# Given a distributor and a product under it
distributor = create(:distributor_enterprise)
product = create(:product, :distributors => [distributor])
# When we view the product
visit spree.product_path(product)
# Then we should see a choice of distributor, with no default
page.should have_selector "select#distributor_id option", :text => distributor.name
page.should_not have_selector "select#distributor_id option[selected='selected']"
end
it "displays the local distributor as the default choice when available for the current product" do
# Given a distributor and a product under it
distributor1 = create(:distributor_enterprise)
distributor2 = create(:distributor_enterprise)
product = create(:product, :distributors => [distributor1,distributor2])
# When we select the distributor and view the product
visit spree.select_distributor_order_path(distributor1)
visit spree.product_path(product)
# Then we should see our distributor as the default option when adding the item to our cart
page.should have_selector "select#distributor_id option[value='#{distributor1.id}'][selected='selected']"
end
it "works when viewing a product from a remote distributor" do
# Given two distributors and our product under one
distributor_product = create(:distributor_enterprise)
distributor_no_product = create(:distributor_enterprise)
product = create(:product, :distributors => [distributor_product])
create(:product, :distributors => [distributor_no_product])
# When we select the distributor without the product and then view the product
visit spree.select_distributor_order_path(distributor_no_product)
visit spree.root_path
visit spree.product_path(product)
# Then we should be told that our distributor will be set to the one with the product
page.should_not have_selector "select#distributor_id"
page.should have_content "our distributor for this order will be changed to #{distributor_product.name} if you add this product to your cart."
end
end
end
describe "selecting an order cycle" do
before(:each) do
OrderCyclesHelper.class_eval do
def order_cycles_enabled?
true
end
end
end
it "displays the distributor and order cycle name on the home page when an order cycle is selected" do
# Given a distributor with a product
d = create(:distributor_enterprise, :name => 'Melb Uni Co-op')
p = create(:product)
oc = create(:simple_order_cycle, :name => 'Bulk Foods', :distributors => [d], :variants => [p.master])
# When I select the distributor and order cycle
visit spree.product_path p
select d.name, :from => 'distributor_id'
select oc.name, :from => 'order_cycle_id'
click_button 'Add To Cart'
# Then I should see the name of the distributor and order cycle that I've selected
page.should have_content 'Melb Uni Co-op'
page.should_not have_selector 'div.distributor-description'
end
end
end

View File

@@ -122,6 +122,7 @@ feature %q{
click_button 'Add To Cart'
# Then I should see a breakdown of my delivery fees:
checkout_fees_table.should ==
[["Bananas - packing fee by supplier Supplier 1", "$3.00", ""],
["Bananas - transport fee by supplier Supplier 1", "$4.00", ""],

View File

@@ -279,25 +279,6 @@ feature %q{
page.should have_selector "input[value='#{@oc1.id}'][checked='checked']"
page.should have_selector "option[value='#{@d1.id}'][selected='selected']"
end
scenario "selection form is not shown when there are products in the cart" do
# Given a product
d = create(:distributor_enterprise)
p = create(:product, :distributors => [d])
# When I go to the products listing page, I should see the selection form
visit spree.products_path
page.should have_selector "#distribution-selection"
# When I add a product to the cart
visit spree.product_path p
select d.name, :from => 'distributor_id'
click_button 'Add To Cart'
# Then I should no longer see the selection form
visit spree.products_path
page.should_not have_selector "#distribution-selection"
end
end
end

View File

@@ -51,24 +51,5 @@ feature %q{
end
end
end
context "with Javascript", js: true do
it "changes distributor details when the distributor is changed" do
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
d3 = create(:distributor_enterprise)
p = create(:product, :distributors => [d1, d2, d3])
visit spree.product_path p
[d1, d2, d3].each do |d|
select d.name, :from => 'distributor_id'
within '#product-distributor-details' do
page.should have_selector 'h2', :text => d.name
end
end
end
end
end
end

View File

@@ -0,0 +1,136 @@
require 'spec_helper'
feature "As a consumer I want to shop with a distributor", js: true do
include AuthenticationWorkflow
include WebHelper
describe "Viewing a distributor" do
let(:distributor) { create(:distributor_enterprise) }
before do #temporarily using the old way to select distributor
create_enterprise_group_for distributor
visit "/"
click_link distributor.name
end
it "shows a distributor" do
visit shop_path
page.should have_text distributor.name
end
describe "With products in order cycles" do
let(:supplier) { create(:supplier_enterprise) }
let(:product) { create(:product, supplier: supplier) }
let(:order_cycle) { create(:order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) }
before do
exchange = Exchange.find(order_cycle.exchanges.to_enterprises(distributor).outgoing.first.id)
exchange.variants << product.master
end
it "shows the suppliers/producers for a distributor" do
visit shop_path
click_link "Our Producers"
page.should have_content supplier.name
end
end
describe "selecting an order cycle" do
it "selects an order cycle if only one is open" do
# create order cycle
oc1 = create(:simple_order_cycle, distributors: [distributor])
exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id)
exchange.update_attribute :pickup_time, "turtles"
visit shop_path
page.should have_selector "option[selected]", text: 'turtles'
end
describe "with multiple order cycles" do
let(:oc1) {create(:simple_order_cycle, distributors: [distributor])}
let(:oc2) {create(:simple_order_cycle, distributors: [distributor])}
before do
exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id)
exchange.update_attribute :pickup_time, "frogs"
exchange = Exchange.find(oc2.exchanges.to_enterprises(distributor).outgoing.first.id)
exchange.update_attribute :pickup_time, "turtles"
end
it "shows a select with all order cycles" do
visit shop_path
page.should have_selector "option", text: 'frogs'
page.should have_selector "option", text: 'turtles'
end
describe "with products in our order cycle" do
let(:product) { create(:simple_product) }
before do
exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id)
exchange.variants << product.master
visit shop_path
end
it "allows us to select an order cycle" do
select "frogs", :from => "order_cycle_id"
Spree::Order.last.order_cycle.should == nil
page.should have_selector "products"
page.should have_content "Orders close #{oc1.orders_close_at.strftime('%A %m')}"
Spree::Order.last.order_cycle.should == oc1
end
it "doesn't show products before an order cycle is selected" do
page.should_not have_content product.name
end
it "shows products when an order cycle has been selected" do
select "frogs", :from => "order_cycle_id"
page.should have_content product.name
end
it "updates the orders close note when order cycle is changed" do
select "frogs", :from => "order_cycle_id"
page.should have_content "Orders close #{oc1.orders_close_at.strftime('%A %m')}"
end
end
end
describe "adding products to cart" do
let(:oc) { create(:simple_order_cycle, distributors: [distributor]) }
let(:product) { create(:simple_product) }
let(:variant) { create(:variant, product: product) }
before do
exchange = Exchange.find(oc.exchanges.to_enterprises(distributor).outgoing.first.id)
exchange.update_attribute :pickup_time, "frogs"
exchange.variants << product.master
exchange.variants << variant
visit shop_path
select "frogs", :from => "order_cycle_id"
end
it "should let us add products to our cart" do
fill_in "variants[#{variant.id}]", with: "1"
first("form.custom > input.button.right").click
current_path.should == "/cart"
page.should have_content product.name
end
end
context "when no order cycles are available" do
it "tells us orders are closed" do
visit shop_path
page.should have_content "Orders are currently closed for this hub"
end
it "shows the last order cycle" do
oc1 = create(:simple_order_cycle, distributors: [distributor], orders_close_at: 10.days.ago)
visit shop_path
page.should have_content "The last cycle closed 10 days ago"
end
it "shows the next order cycle" do
oc1 = create(:simple_order_cycle, distributors: [distributor], orders_open_at: 10.days.from_now)
visit shop_path
page.should have_content "The next cycle opens in 10 days"
end
end
end
end
end

View File

@@ -33,4 +33,16 @@ describe OrderCyclesHelper do
helper.pickup_time.should == "turtles"
end
it "should give 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])
exchange = Exchange.find(oc2.exchanges.to_enterprises(d).outgoing.first.id)
exchange.update_attribute :pickup_time, "turtles"
helper.stub!(:current_order_cycle).and_return oc1
helper.stub!(:current_distributor).and_return d
helper.pickup_time(oc2).should == "turtles"
end
end

View File

@@ -0,0 +1,11 @@
require 'spec_helper'
describe ShopHelper do
it "should build order cycle select options" do
d = create(:distributor_enterprise)
o1 = create(:simple_order_cycle, distributors: [d])
helper.stub(:current_distributor).and_return d
helper.order_cycles_name_and_pickup_times([o1]).should == [[helper.pickup_time(o1), o1.id]]
end
end

View File

@@ -1,4 +1,4 @@
describe "filtering products", ->
describe "filtering products for submission to database", ->
it "accepts an object or an array and only returns an array", ->
expect(filterSubmitProducts([])).toEqual []
expect(filterSubmitProducts({})).toEqual []
@@ -276,15 +276,41 @@ describe "AdminBulkProductsCtrl", ->
it "gets a list of suppliers and then resets products with a list of data", ->
httpBackend.expectGET("/api/users/authorise_api?token=api_key").respond success: "Use of API Authorised"
httpBackend.expectGET("/api/enterprises/managed?template=bulk_index&q[is_primary_producer_eq]=true").respond "list of suppliers"
httpBackend.expectGET("/api/products/managed?template=bulk_index;page=1;per_page=500").respond "list of products"
spyOn scope, "resetProducts"
spyOn(scope, "fetchProducts").andReturn "nothing"
scope.initialise "api_key"
httpBackend.flush()
expect(scope.suppliers).toEqual "list of suppliers"
expect(scope.resetProducts).toHaveBeenCalledWith "list of products"
expect(scope.fetchProducts.calls.length).toEqual 1
expect(scope.spree_api_key_ok).toEqual true
describe "fetching products", ->
it "makes a standard call to dataFetcher when no filters exist", ->
httpBackend.expectGET("/api/products/managed?template=bulk_index;page=1;per_page=500;").respond "list of products"
scope.fetchProducts()
it "calls resetProducts after data has been received", ->
spyOn scope, "resetProducts"
httpBackend.expectGET("/api/products/managed?template=bulk_index;page=1;per_page=500;").respond "list of products"
scope.fetchProducts()
httpBackend.flush()
expect(scope.resetProducts).toHaveBeenCalledWith "list of products"
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/managed?template=bulk_index;page=1;per_page=500;q[name_eq]=Product1;").respond "list of products"
scope.fetchProducts()
it "sets the loading property to true before fetching products and unsets it when loading is complete", ->
httpBackend.expectGET("/api/products/managed?template=bulk_index;page=1;per_page=500;").respond "list of products"
scope.fetchProducts()
expect(scope.loading).toEqual true
httpBackend.flush()
expect(scope.loading).toEqual false
describe "resetting products", ->
beforeEach ->
spyOn scope, "unpackProduct"
@@ -681,6 +707,7 @@ describe "AdminBulkProductsCtrl", ->
]
scope.updateProducts "list of dirty products"
httpBackend.flush()
timeout.flush()
expect(scope.displaySuccess).toHaveBeenCalled()
it "runs displayFailure() when post return data does not match $scope.products", ->
@@ -972,6 +999,62 @@ describe "AdminBulkProductsCtrl", ->
]
describe "filtering products", ->
describe "adding a filter to the filter list", ->
it "adds objects sent to addFilter() to $scope.currentFilters", ->
spyOn(scope, "fetchProducts").andReturn "nothing"
filterObject1 = {property: scope.filterableColumns[0], predicate: scope.filterTypes[0], value: "Product1"}
filterObject2 = {property: scope.filterableColumns[0], predicate: scope.filterTypes[0], value: "Product2"}
scope.addFilter filterObject1
scope.addFilter filterObject2
expect(scope.currentFilters).toEqual [filterObject1, filterObject2]
it "ignores objects sent to addFilter() which do not contain a 'property' with a corresponding key in filterableColumns", ->
spyOn(scope, "fetchProducts").andReturn "nothing"
filterObject1 = {property: scope.filterableColumns[0], predicate: scope.filterTypes[0], value: "value1"}
filterObject2 = {property: scope.filterableColumns[1], predicate: scope.filterTypes[0], value: "value2"}
filterObject3 = {property: "some_random_property", predicate: scope.filterTypes[0], value: "value3"}
scope.addFilter filterObject1
scope.addFilter filterObject2
scope.addFilter filterObject3
expect(scope.currentFilters).toEqual [filterObject1, filterObject2]
it "ignores objects sent to addFilter() which do not contain a query with a corresponding key in filterTypes", ->
spyOn(scope, "fetchProducts").andReturn "nothing"
filterObject1 = {property: scope.filterableColumns[0], predicate: scope.filterTypes[0], value: "value1"}
filterObject2 = {property: scope.filterableColumns[0], predicate: scope.filterTypes[1], value: "value2"}
filterObject3 = {property: scope.filterableColumns[0], predicate: "something", value: "value3"}
scope.addFilter filterObject1
scope.addFilter filterObject2
scope.addFilter filterObject3
expect(scope.currentFilters).toEqual [filterObject1, filterObject2]
it "calls fetchProducts when adding a new filter", ->
spyOn(scope, "fetchProducts").andReturn "nothing"
scope.addFilter( { property: scope.filterableColumns[0], predicate: scope.filterTypes[0], value: "value1" } )
expect(scope.fetchProducts.calls.length).toEqual(1)
describe "removing a filter from the filter list", ->
filterObject1 = filterObject2 = null
beforeEach ->
filterObject1 = {property: scope.filterableColumns[0], predicate: scope.filterTypes[0], value: "Product1"}
filterObject2 = {property: scope.filterableColumns[0], predicate: scope.filterTypes[0], value: "Product2"}
scope.currentFilters = [ filterObject1, filterObject2 ]
it "removes the specified filter from $scope.currentFilters and calls fetchProducts", ->
spyOn(scope, "fetchProducts").andReturn "nothing"
scope.removeFilter filterObject1
expect(scope.currentFilters).toEqual [ filterObject2 ]
expect(scope.fetchProducts.calls.length).toEqual 1
it "ignores filters which do not exist in currentFilters", ->
spyOn(scope, "fetchProducts").andReturn "nothing"
filterObject3 = {property: scope.filterableColumns[1], predicate: scope.filterTypes[1], value: "SomethingElse"}
scope.removeFilter filterObject3
expect(scope.currentFilters).toEqual [ filterObject1, filterObject2 ]
expect(scope.fetchProducts.calls.length).toEqual 0
describe "converting arrays of objects with ids to an object with ids as keys", ->
it "returns an object", ->

View File

@@ -0,0 +1,40 @@
describe 'All controllers', ->
describe 'ProductsCtrl', ->
ctrl = null
scope = null
event = null
rootScope = null
Product = null
beforeEach ->
module('Shop')
Product =
all: ->
update: ->
data: "testy mctest"
inject ($controller, $rootScope) ->
rootScope = $rootScope
scope = $rootScope.$new()
ctrl = $controller 'ProductsCtrl', {$scope: scope, Product : Product}
it 'Fetches products from Product', ->
expect(scope.data).toEqual 'testy mctest'
describe 'OrderCycleCtrl', ->
ctrl = null
scope = null
event = null
rootScope = null
product_ctrl = null
OrderCycle = null
beforeEach ->
module 'Shop'
scope = {}
inject ($controller, $rootScope) ->
rootScope = $rootScope
scope = $rootScope.$new()
ctrl = $controller 'OrderCycleCtrl', {$scope: scope}

View File

@@ -0,0 +1,34 @@
describe 'OrderCycle service', ->
$httpBackend = null
OrderCycle = null
mockProduct = {
update: ->
}
beforeEach ->
angular.module('Shop').value('orderCycleData', {})
module 'Shop', ($provide)->
$provide.value "Product", mockProduct
null # IMPORTANT
# You must return null because module() is a bit dumb
inject (_OrderCycle_, _$httpBackend_)->
$httpBackend = _$httpBackend_
OrderCycle = _OrderCycle_
it "posts the order_cycle ID and tells product to update", ->
$httpBackend.expectPOST("/shop/order_cycle", {"order_cycle_id" : 10}).respond(200)
spyOn(mockProduct, "update")
OrderCycle.order_cycle.order_cycle_id = 10
OrderCycle.push_order_cycle()
$httpBackend.flush()
expect(mockProduct.update).toHaveBeenCalled()
it "updates the orders_close_at attr after update", ->
datestring = "2013-12-20T00:00:00+11:00"
$httpBackend.expectPOST("/shop/order_cycle").respond({orders_close_at: datestring})
OrderCycle.push_order_cycle()
$httpBackend.flush()
expect(OrderCycle.order_cycle.orders_close_at).toEqual(datestring)

View File

@@ -0,0 +1,14 @@
describe 'Product service', ->
$httpBackend = null
Product = null
beforeEach ->
module 'Shop'
inject ($injector, _$httpBackend_)->
Product = $injector.get("Product")
$httpBackend = _$httpBackend_
it "Fetches products from the backend on init", ->
$httpBackend.expectGET("/shop/products").respond([{test : "cats"}])
products = Product.all()
$httpBackend.flush()

View File

@@ -754,4 +754,4 @@ describe 'OrderCycle services', ->
expect(data.incoming_exchanges[0].enterprise_fees).toBeUndefined()
expect(data.outgoing_exchanges[0].enterprise_fees).toBeUndefined()
expect(data.incoming_exchanges[0].enterprise_fee_ids).toEqual [1, 2]
expect(data.outgoing_exchanges[0].enterprise_fee_ids).toEqual [3, 4]
expect(data.outgoing_exchanges[0].enterprise_fee_ids).toEqual [3, 4]

View File

@@ -7,59 +7,20 @@ module Spree
let(:params) { double(:params) }
let(:distributor) { double(:distributor) }
let(:order_cycle) { double(:order_cycle) }
let(:orig_distributor) { double(:distributor) }
let(:orig_order_cycle) { double(:order_cycle) }
let(:op) { OrderPopulator.new(order, currency) }
describe "populate" do
it "checks that distribution can supply all products in the cart" do
op.should_receive(:load_distributor_and_order_cycle).with(params).
op.should_receive(:distributor_and_order_cycle).
and_return([distributor, order_cycle])
op.should_receive(:distribution_can_supply_products_in_cart).
with(distributor, order_cycle).and_return(false)
op.stub(:orig_distributor_and_order_cycle).and_return([orig_distributor,
orig_order_cycle])
op.should_receive(:populate_without_distribution_validation).never
op.should_receive(:set_cart_distributor_and_order_cycle).never
op.populate(params).should be_false
op.errors.to_a.should == ["That distributor or order cycle can't supply all the products in your cart. Please choose another."]
end
it "resets cart distributor and order cycle if populate fails" do
op.should_receive(:load_distributor_and_order_cycle).with(params).
and_return([distributor, order_cycle])
op.should_receive(:distribution_can_supply_products_in_cart).
with(distributor, order_cycle).and_return(true)
op.stub(:orig_distributor_and_order_cycle).and_return([orig_distributor,
orig_order_cycle])
op.class_eval do
def populate_without_distribution_validation(from_hash)
errors.add(:base, "Something went wrong.")
end
end
op.should_receive(:set_cart_distributor_and_order_cycle).with(distributor, order_cycle)
op.should_receive(:set_cart_distributor_and_order_cycle).with(orig_distributor, orig_order_cycle)
op.populate(params).should be_false
op.errors.to_a.should == ["Something went wrong."]
end
it "sets cart distributor and order cycle when populate succeeds" do
op.should_receive(:load_distributor_and_order_cycle).with(params).
and_return([distributor, order_cycle])
op.should_receive(:distribution_can_supply_products_in_cart).
with(distributor, order_cycle).and_return(true)
op.stub(:orig_distributor_and_order_cycle).and_return([orig_distributor,
orig_order_cycle])
op.should_receive(:populate_without_distribution_validation).with(params)
op.should_receive(:set_cart_distributor_and_order_cycle).with(distributor, order_cycle)
op.populate(params).should be_true
end
end
describe "attempt_cart_add" do
@@ -69,7 +30,7 @@ module Spree
Spree::Variant.stub(:find).and_return(variant)
op.should_receive(:check_stock_levels).with(variant, quantity).and_return(true)
op.should_receive(:check_distribution_provided_for).with(variant).and_return(true)
op.should_receive(:check_order_cycle_provided_for).with(variant).and_return(true)
op.should_receive(:check_variant_available_under_distribution).with(variant).
and_return(true)
order.should_receive(:add_variant).with(variant, quantity, currency)
@@ -89,30 +50,22 @@ module Spree
end
end
describe "checking distribution is provided for a variant" do
describe "checking order cycle is provided for a variant, OR is not needed" do
let(:variant) { double(:variant) }
it "returns false and errors when distribution is not provided and order cycle is required" do
op.should_receive(:distribution_provided_for).with(variant).and_return(false)
op.should_receive(:order_cycle_required_for).with(variant).and_return(true)
op.send(:check_distribution_provided_for, variant).should be_false
op.errors.to_a.should == ["Please choose a distributor and order cycle for this order."]
it "returns false and errors when order cycle is not provided and is required" do
op.stub(:order_cycle_required_for).and_return true
op.send(:check_order_cycle_provided_for, variant).should be_false
op.errors.to_a.should == ["Please choose an order cycle for this order."]
end
it "returns false and errors when distribution is not provided and order cycle is not required" do
op.should_receive(:distribution_provided_for).with(variant).and_return(false)
op.should_receive(:order_cycle_required_for).with(variant).and_return(false)
op.send(:check_distribution_provided_for, variant).should be_false
op.errors.to_a.should == ["Please choose a distributor for this order."]
it "returns true when order cycle is provided" do
op.stub(:order_cycle_required_for).and_return true
op.instance_variable_set :@order_cycle, double(:order_cycle)
op.send(:check_order_cycle_provided_for, variant).should be_true
end
it "returns true and does not error otherwise" do
op.should_receive(:distribution_provided_for).with(variant).and_return(true)
op.send(:check_distribution_provided_for, variant).should be_true
op.errors.should be_empty
it "returns true when order cycle is not required" do
op.stub(:order_cycle_required_for).and_return false
op.send(:check_order_cycle_provided_for, variant).should be_true
end
end
@@ -142,60 +95,6 @@ module Spree
describe "support" do
describe "loading distributor and order cycle from hash" do
it "loads distributor and order cycle when present" do
params = {distributor_id: 1, order_cycle_id: 2}
distributor = double(:distributor)
order_cycle = double(:order_cycle)
enterprise_scope = double(:enterprise_scope)
enterprise_scope.should_receive(:find).with(1).and_return(distributor)
Enterprise.should_receive(:is_distributor).and_return(enterprise_scope)
OrderCycle.should_receive(:find).with(2).and_return(order_cycle)
op.send(:load_distributor_and_order_cycle, params).should ==
[distributor, order_cycle]
end
it "returns nil when not present" do
op.send(:load_distributor_and_order_cycle, {}).should == [nil, nil]
end
end
it "sets cart distributor and order cycle" do
Spree::Order.should_receive(:find).with(order.id).and_return(order)
order.should_receive(:set_distribution!).with(distributor, order_cycle)
op.send(:set_cart_distributor_and_order_cycle, distributor, order_cycle)
end
describe "checking if distribution is provided for a variant" do
let(:variant) { double(:variant) }
it "returns false when distributor is nil" do
op.instance_eval { @distributor = nil }
op.send(:distribution_provided_for, variant).should be_false
end
it "returns false when order cycle is nil when it's required" do
op.instance_eval { @distributor = 1; @order_cycle = nil }
op.should_receive(:order_cycle_required_for).with(variant).and_return(true)
op.send(:distribution_provided_for, variant).should be_false
end
it "returns true when distributor is present and order cycle is not required" do
op.instance_eval { @distributor = 1; @order_cycle = nil }
op.should_receive(:order_cycle_required_for).with(variant).and_return(false)
op.send(:distribution_provided_for, variant).should be_true
end
it "returns true when distributor is present and order cycle is required and present" do
op.instance_eval { @distributor = 1; @order_cycle = 1 }
op.should_receive(:order_cycle_required_for).with(variant).and_return(true)
op.send(:distribution_provided_for, variant).should be_true
end
end
describe "checking if order cycle is required for a variant" do
it "requires an order cycle when the product has no product distributions" do
product = double(:product, product_distributions: [])
@@ -210,11 +109,11 @@ module Spree
end
end
it "provides the original distributor and order cycle for the order" do
order.should_receive(:distributor).and_return(orig_distributor)
order.should_receive(:order_cycle).and_return(orig_order_cycle)
op.send(:orig_distributor_and_order_cycle).should == [orig_distributor,
orig_order_cycle]
it "provides the distributor and order cycle for the order" do
order.should_receive(:distributor).and_return(distributor)
order.should_receive(:order_cycle).and_return(order_cycle)
op.send(:distributor_and_order_cycle).should == [distributor,
order_cycle]
end
end
end

View File

@@ -15,7 +15,7 @@ module Spree
sm.distributors << d1
sm.distributors << d2
sm.reload.distributors.should == [d1, d2]
sm.reload.distributors.sort.should == [d1, d2].sort
end
it "finds shipping methods for a particular distributor" do

View File

@@ -32,13 +32,15 @@ ActiveRecord::Fixtures.create_fixtures(fixtures_dir, ['spree/states', 'spree/cou
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist
# For debugging:
# - Extend poltergeist's timeout to allow ample time to use pry in browser thread
# - Enable the remote inspector: Use page.driver.debug to open a remote debugger in chrome
# Capybara.register_driver :poltergeist do |app|
# Capybara::Poltergeist::Driver.new(app, timeout: 5.minutes)
# Capybara::Poltergeist::Driver.new(app, inspector: true)
# end
Capybara.register_driver :poltergeist do |app|
options = {phantomjs_options: ['--load-images=no']}
# Extend poltergeist's timeout to allow ample time to use pry in browser thread
#options.merge! {timeout: 5.minutes}
# Enable the remote inspector: Use page.driver.debug to open a remote debugger in chrome
#options.merge! {inspector: true}
Capybara::Poltergeist::Driver.new(app, options)
end
require "paperclip/matchers"
@@ -92,6 +94,7 @@ RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.include OpenFoodNetwork::FeatureToggleHelper
config.include OpenFoodNetwork::EnterpriseGroupsHelper
config.include OpenFoodNetwork::DistributionHelper
config.include ActionView::Helpers::DateHelper
# Factory girl

View File

@@ -1,13 +1,12 @@
module AuthenticationWorkflow
def login_to_admin_section
admin_role = Spree::Role.find_or_create_by_name!('admin')
admin_user = Spree::User.create!({
:email => 'admin@ofn.org',
admin_user = create(:user,
:password => 'passw0rd',
:password_confirmation => 'passw0rd',
:remember_me => false,
:persistence_token => 'pass',
:login => 'admin@ofn.org'})
:login => 'admin@ofn.org')
admin_user.spree_roles << admin_role

View File

@@ -0,0 +1,14 @@
module OpenFoodNetwork
module DistributionHelper
def select_distribution(distributor, order_cycle=nil)
create_enterprise_group_for distributor
visit root_path
click_link distributor.name
if order_cycle && page.has_select?('order_order_cycle_id')
select_by_value order_cycle.id, from: 'order_order_cycle_id'
end
end
end
end