Merge pull request #4471 from luisramos0/paginate_exc_prods

Paginate Exchange Products API endpoint
This commit is contained in:
Luis Ramos
2019-12-17 15:25:15 +00:00
committed by GitHub
21 changed files with 299 additions and 107 deletions

View File

@@ -1,4 +1,4 @@
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, OrderCycle, ocInstance) ->
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, OrderCycle, ExchangeProduct, ocInstance) ->
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.view = 'incoming'
@@ -9,19 +9,23 @@ angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($
enterprise = $scope.enterprises[exchange.enterprise_id]
return enterprise.numVariants if enterprise.numVariants?
$scope.loadExchangeProducts(exchange)
return unless enterprise.supplied_products?
enterprise.numVariants = 0
params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: true}
ExchangeProduct.countVariants params, (variants_count) ->
enterprise.numVariants = variants_count
$scope.setSelectAllVariantsCheckboxValue(exchange, enterprise.numVariants)
enterprise.numVariants = $scope.countVariants(enterprise.supplied_products)
$scope.countVariants = (products) ->
return 0 unless products
numVariants = 0
for product in products
numVariants += product.variants.length
numVariants
return enterprise.numVariants
$scope.addSupplier = ($event) ->
$event.preventDefault()
OrderCycle.addSupplier $scope.new_supplier_id
# To select all variants we first need to load them all from the server
#
# This is only needed in Incoming exchanges as here we use supplied_products,
# in Outgoing Exchanges the variants are loaded as part of the Exchange payload
$scope.selectAllVariants = (exchange, selected) ->
$scope.loadAllExchangeProducts(exchange).then ->
$scope.setExchangeVariants(exchange, $scope.suppliedVariants(exchange.enterprise_id), selected)
$scope.$apply()

View File

@@ -18,11 +18,11 @@ angular.module('admin.orderCycles')
$scope.cancel = (destination) ->
$window.location = destination
# Used in panels/exchange_supplied_products.html
# Used in panels/exchange_products_supplied.html
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
# Used in panels/exchange_supplied_products.html and panels/exchange_distributed_products.html
# Used in panels/exchange_products_supplied.html and panels/exchange_products_distributed.html
$scope.setExchangeVariants = (exchange, variants, selected) ->
OrderCycle.setExchangeVariants(exchange, variants, selected)

View File

@@ -5,6 +5,12 @@ angular.module('admin.orderCycles')
$scope.supplier_enterprises = Enterprise.producer_enterprises
$scope.distributor_enterprises = Enterprise.hub_enterprises
$scope.productsLoading = ->
RequestMonitor.loading
$scope.setSelectAllVariantsCheckboxValue = (exchange, totalNumberOfVariants) ->
exchange.select_all_variants = $scope.exchangeSelectedVariants(exchange) >= totalNumberOfVariants
$scope.exchangeSelectedVariants = (exchange) ->
OrderCycle.exchangeSelectedVariants(exchange)
@@ -36,18 +42,35 @@ angular.module('admin.orderCycles')
$scope.removeDistributionOfVariant = (variant_id) ->
OrderCycle.removeDistributionOfVariant(variant_id)
$scope.loadExchangeProducts = (exchange) ->
return if $scope.enterprises[exchange.enterprise_id].supplied_products_fetched?
$scope.enterprises[exchange.enterprise_id].supplied_products_fetched = true
$scope.loadExchangeProducts = (exchange, page = 1) ->
enterprise = $scope.enterprises[exchange.enterprise_id]
enterprise.supplied_products ?= []
return if enterprise.last_page_loaded? && enterprise.last_page_loaded >= page
enterprise.last_page_loaded = page
incoming = true if $scope.view == 'incoming'
params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming}
ExchangeProduct.index params, (products) ->
$scope.enterprises[exchange.enterprise_id].supplied_products = products
params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming, page: page}
ExchangeProduct.index params, (products, num_of_pages, num_of_products) ->
enterprise.num_of_pages = num_of_pages
enterprise.num_of_products = num_of_products
enterprise.supplied_products.push products...
$scope.loadMoreExchangeProducts = (exchange) ->
$scope.loadExchangeProducts(exchange, $scope.enterprises[exchange.enterprise_id].last_page_loaded + 1)
$scope.loadAllExchangeProducts = (exchange) ->
enterprise = $scope.enterprises[exchange.enterprise_id]
if enterprise.last_page_loaded < enterprise.num_of_pages
for page_to_load in [(enterprise.last_page_loaded + 1)..enterprise.num_of_pages]
RequestMonitor.load $scope.loadExchangeProducts(exchange, page_to_load).$promise
RequestMonitor.loadQueue
# initialize exchange products panel if not yet done
$scope.exchangeProdutsPanelInitialized = []
$scope.initializeExchangeProductsPanel = (exchange) ->
return if $scope.exchangeProdutsPanelInitialized[exchange.enterprise_id]
$scope.loadExchangeProducts(exchange)
RequestMonitor.load $scope.loadExchangeProducts(exchange).$promise
$scope.exchangeProdutsPanelInitialized[exchange.enterprise_id] = true

View File

@@ -9,6 +9,11 @@ angular.module('admin.orderCycles').controller 'AdminOrderCycleOutgoingCtrl', ($
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
$scope.exchangeTotalVariants = (exchange) ->
totalNumberOfVariants = $scope.incomingExchangeVariantsFor(exchange.enterprise_id).length
$scope.setSelectAllVariantsCheckboxValue(exchange, totalNumberOfVariants)
totalNumberOfVariants
$scope.addDistributor = ($event) ->
$event.preventDefault()
OrderCycle.addDistributor $scope.new_distributor_id

View File

@@ -1,15 +1,16 @@
angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) ->
ExchangeProductResource = $resource('/api/exchanges/:exchange_id/products.json', {}, {
'index':
method: 'GET'
isArray: true
'index': { method: 'GET' }
'variant_count': { method: 'GET', params: { action_name: "variant_count" }}
})
{
ExchangeProductResource: ExchangeProductResource
loaded: false
index: (params={}, callback=null) ->
ExchangeProductResource.index params, (data) =>
@loaded = true
(callback || angular.noop)(data)
(callback || angular.noop)(data.products, data.pagination.pages, data.pagination.results)
countVariants: (params={}, callback=null) ->
ExchangeProductResource.variant_count params, (data) =>
(callback || angular.noop)(data.count)
})

View File

@@ -1,5 +1,7 @@
.row.exchange-distributed-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'}
.sixteen.columns.alpha.omega
.sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' }
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_header.html'" }
.exchange-select-all-variants
%label
%input{ type: 'checkbox', name: 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants',
@@ -7,10 +9,9 @@
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'setExchangeVariants(exchange, incomingExchangeVariantsFor(exchange.enterprise_id), exchange.select_all_variants)',
'id' => 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants' }
{{ 'admin.select_all' | t }}
{{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
.exchange-products
-# Scope product list based on permissions the current user has to view variants in this exchange
.exchange-products{ 'ng-hide' => 'productsLoading()' }
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products | filter:visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' }
.exchange-product-details
%label
@@ -26,3 +27,5 @@
'id' => 'order_cycle_outgoing_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
'ng-disabled' => '!order_cycle.editable_variants_for_outgoing_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_outgoing_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' }
{{ variant.label }}
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_footer.html'" }

View File

@@ -0,0 +1,11 @@
.pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages && !productsLoading()'}
.button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' }
{{ 'js.admin.panels.exchange_products.load_more_products' | t }}
.button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' }
{{ 'js.admin.panels.exchange_products.load_all_products' | t }}
.sixteen.columns.alpha#loading{ 'ng-show' => 'productsLoading()' }
%br
%img.spinner{ src: "/assets/spinning-circles.svg" }
%h1
{{ 'js.admin.panels.exchange_products.loading_products' | t }}

View File

@@ -0,0 +1,5 @@
.exchange-load-all-variants
%div
{{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
%a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' }
{{ 'js.admin.panels.exchange_products.load_all_products' | t }}

View File

@@ -0,0 +1,12 @@
.row.exchange-supplied-products
.sixteen.columns.alpha.omega
.exchange-select-all-variants
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants',
value: 1,
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)',
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
{{ 'admin.select_all' | t }}
%div{ 'ng-include' => "'admin/panels/exchange_products_supplied_list.html'" }

View File

@@ -0,0 +1,16 @@
.row.exchange-supplied-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'}
.sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' }
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_header.html'" }
.exchange-select-all-variants
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants',
value: 1,
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'selectAllVariants(exchange, exchange.select_all_variants)',
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
{{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
%div{ 'ng-include' => "'admin/panels/exchange_products_supplied_list.html'" }
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_footer.html'" }

View File

@@ -0,0 +1,16 @@
.exchange-products{ 'ng-hide' => 'productsLoading()' }
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'}
.exchange-product-details
%label
%img{'ng-src' => '{{ product.image_url }}'}
{{ product.name }}
.exchange-product-variant{'ng-repeat' => 'variant in product.variants'}
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
value: 1,
'ng-model' => 'exchange.variants[variant.id]',
'ofn-sync-distributions' => '{{ variant.id }}',
'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' }
{{ variant.label }}

View File

@@ -1,29 +0,0 @@
.row.exchange-supplied-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'}
.sixteen.columns.alpha.omega
.exchange-select-all-variants
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants',
value: 1,
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)',
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
{{ 'admin.select_all' | t }}
.exchange-products
-# No need to scope product list based on permissions, because if an incoming exchange is visible,
-# then all of the variants within it should be visible. May change in the future?
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'}
.exchange-product-details
%label
%img{'ng-src' => '{{ product.image_url }}'}
{{ product.name }}
.exchange-product-variant{'ng-repeat' => 'variant in product.variants'}
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
value: 1,
'ng-model' => 'exchange.variants[variant.id]',
'ofn-sync-distributions' => '{{ variant.id }}',
'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' }
{{ variant.label }}

View File

@@ -104,9 +104,13 @@ form.order_cycle {
width: 20px;
}
.exchange-load-all-variants {
margin: 0px 5px 20px 5px;
}
.exchange-select-all-variants {
clear: both;
margin: 5px;
margin: 15px 5px 25px 5px;
}
.exchange-products {
@@ -209,6 +213,7 @@ table#listing_enterprise_groups {
#loading {
text-align: center;
img.spinner {
border: 0px;
width: 100px;
height: 100px;
}

View File

@@ -1,6 +1,9 @@
# This controller lists products that can be added to an exchange
module Api
class ExchangeProductsController < Api::BaseController
DEFAULT_PAGE = 1
DEFAULT_PER_PAGE = 100
skip_authorization_check only: [:index]
# If exchange_id is present in the URL:
@@ -17,20 +20,32 @@ module Api
load_data_from_other_params
end
render_products
render_variant_count && return if params[:action_name] == "variant_count"
render_paginated_products paginated_products
end
private
def render_products
products = ExchangeProductsRenderer.
def render_variant_count
render text: {
count: Spree::Variant.
not_master.
where(product_id: products).
count
}.to_json
end
def products
ExchangeProductsRenderer.
new(@order_cycle, spree_current_user).
exchange_products(@incoming, @enterprise)
end
render json: products,
each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer,
order_cycle: @order_cycle,
status: :ok
def paginated_products
products.
page(params[:page] || DEFAULT_PAGE).
per(params[:per_page] || DEFAULT_PER_PAGE)
end
def load_data_from_exchange
@@ -51,5 +66,27 @@ module Api
end
@incoming = params[:incoming]
end
def render_paginated_products(paginated_products)
serializer = ActiveModel::ArraySerializer.new(
paginated_products,
each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer,
order_cycle: @order_cycle
)
render text: {
products: serializer,
pagination: pagination_data(paginated_products)
}.to_json
end
def pagination_data(paginated_products)
{
results: paginated_products.total_count,
pages: paginated_products.num_pages,
page: (params[:page] || DEFAULT_PAGE).to_i,
per_page: (params[:per_page] || DEFAULT_PER_PAGE).to_i
}
end
end
end

View File

@@ -1,11 +1,7 @@
%tr{ ng: { class: "'#{type} #{type}-{{ exchange.enterprise_id }}'" } }
%td{:class => "#{type}_name"} {{ enterprises[exchange.enterprise_id].name }}
%td.products.panel-toggle.text-center{ name: "products" }
{{ exchangeSelectedVariants(exchange) }} /
- if type == 'supplier'
{{ exchangeTotalVariants(exchange) }}
- else
{{ (incomingExchangeVariantsFor(exchange.enterprise_id)).length }}
{{ exchangeSelectedVariants(exchange) }} / {{ exchangeTotalVariants(exchange) }}
= t('.selected')
- if type == 'supplier'
%td.receival-details
@@ -34,11 +30,11 @@
- if type == 'supplier'
%tr.panel-row{ object: "exchange",
panels: "{products: 'exchange_supplied_products'}",
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel",
panels: "{products: 'exchange_products_supplied'}",
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,selectAllVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading",
colspan: 4 }
- if type == 'distributor'
%tr.panel-row{ object: "exchange",
panels: "{products: 'exchange_distributed_products', tags: 'exchange_tags'}",
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel",
panels: "{products: 'exchange_products_distributed', tags: 'exchange_tags'}",
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading",
colspan: 5 }

View File

@@ -17,7 +17,7 @@
%table.exchanges
%tbody{ng: {repeat: "exchange in order_cycle.incoming_exchanges"}}
%tr.products
%td{ ng: { include: "'admin/panels/exchange_supplied_products.html'" } }
%td{ ng: { include: "'admin/panels/exchange_products_simple.html'" } }
%br/
= label_tag t('.fees')

View File

@@ -2560,6 +2560,12 @@ See the %{link} to find out more about %{sitename}'s features and to start using
severity: Severity
description: Description
resolve: Resolve
exchange_products:
load_more_products: "Load More Products"
load_all_products: "Load All Products"
select_all_products: "Select All %{total_number_of_products} Products"
products_loaded: "%{num_of_products_loaded} of %{total_number_of_products} Products Loaded"
loading_products: "Loading Products"
tag_rules:
shipping_method_tagged_top: "Shipping methods tagged"
shipping_method_tagged_bottom: "are:"

View File

@@ -4,31 +4,59 @@ module Api
describe ExchangeProductsController, type: :controller do
include AuthenticationWorkflow
let!(:order_cycle) { create(:order_cycle) }
let!(:coordinator) { order_cycle.coordinator }
let(:order_cycle) { create(:order_cycle) }
let(:exchange) { order_cycle.exchanges.incoming.first }
let(:coordinator) { order_cycle.coordinator }
let!(:renderer) { ExchangeProductsRenderer.new(order_cycle, coordinator.owner) }
before do
allow(controller).to receive_messages spree_current_user: coordinator.owner
allow(ExchangeProductsRenderer).to receive(:new) { renderer }
allow(renderer).
to receive(:exchange_products).
with(exchange.incoming, exchange.sender).
and_return(products_relation)
end
describe "#index" do
describe "for incoming exchanges" do
it "loads data" do
exchange = order_cycle.exchanges.incoming.first
spree_get :index, exchange_id: exchange.id
describe "when the product list is empty" do
let(:products_relation) { Spree::Product.where("1=0") }
expect(json_response.first["supplier_name"]).to eq exchange.variants.first.product.supplier.name
it "handles it gracefully" do
spree_get :index, exchange_id: exchange.id
expect(json_response["products"].length).to eq 0
end
end
describe "for outgoing exchanges" do
it "loads data" do
exchange = order_cycle.exchanges.outgoing.first
spree_get :index, exchange_id: exchange.id
describe "when a product is returned" do
let(:products_relation) { Spree::Product.where(id: exchange.variants.first.product.id) }
suppliers = [exchange.variants[0].product.supplier.name, exchange.variants[1].product.supplier.name]
expect(suppliers).to include json_response.first["supplier_name"]
expect(suppliers).to include json_response.second["supplier_name"]
describe "when an exchange id param is provided" do
it "uses exchange order_cycle, incoming and enterprise to fetch products" do
spree_get :index, exchange_id: exchange.id, order_cycle_id: 666, enterprise_id: 666, incoming: false
expect(json_response["products"].first["supplier_name"]).to eq exchange.variants.first.product.supplier.name
end
end
describe "when an exchange id param is not provided" do
it "uses params order_cycle, incoming and enterprise to fetch products" do
spree_get :index, order_cycle_id: order_cycle.id, enterprise_id: exchange.sender_id, incoming: true
expect(json_response["products"].first["supplier_name"]).to eq exchange.variants.first.product.supplier.name
end
end
end
describe "pagination" do
let(:exchange) { order_cycle.exchanges.outgoing.first }
let(:products_relation) { Spree::Product.includes(:variants).where("spree_variants.id": exchange.variants.map(&:id)) }
it "paginates results" do
spree_get :index, exchange_id: exchange.id, page: 1, per_page: 1
expect(json_response["products"].size).to eq 1
expect(json_response["pagination"]["results"]).to eq 2
expect(json_response["pagination"]["pages"]).to eq 2
end
end
end

View File

@@ -522,6 +522,45 @@ feature '
expect(page).not_to have_selector 'table.exchanges tr.supplier'
end
describe "editing an order cycle with multiple pages of products", js: true do
let(:order_cycle) { create(:order_cycle) }
let(:supplier_enterprise) { order_cycle.exchanges.incoming.first.sender }
let!(:new_product) { create(:product, supplier: supplier_enterprise) }
before do
stub_const("Api::ExchangeProductsController::DEFAULT_PER_PAGE", 1)
quick_login_as_admin
visit admin_order_cycle_incoming_path(order_cycle)
expect(page).to have_content "1 / 2 selected"
page.find("tr.supplier-#{supplier_enterprise.id} td.products").click
expect(page).to have_selector ".exchange-product-details"
expect(page).to have_content "1 of 2 Products Loaded"
expect(page).to_not have_content new_product.name
end
scenario "load all products" do
page.find(".exchange-load-all-variants a").click
expect_all_products_loaded
end
scenario "select all products" do
check "order_cycle_incoming_exchange_0_select_all_variants"
expect_all_products_loaded
expect(page).to have_checked_field "order_cycle_incoming_exchange_0_variants_#{new_product.variants.first.id}", disabled: false
end
def expect_all_products_loaded
expect(page).to have_content new_product.name.upcase
expect(page).to have_content "2 of 2 Products Loaded"
end
end
scenario "updating many order cycle opening/closing times at once", js: true do
# Given three order cycles
oc1 = create(:simple_order_cycle)

View File

@@ -23,21 +23,6 @@ describe 'AdminOrderCycleIncomingCtrl', ->
inject ($controller) ->
ctrl = $controller 'AdminOrderCycleIncomingCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee, ocInstance: ocInstance}
it 'counts total variants in a list of products', ->
products = [
{variants: [{}]},
{variants: [{}]},
{variants: [{}, {}, {}]}
]
expect(scope.countVariants(products)).toEqual(5)
it 'returns zero when products list is null', ->
expect(scope.countVariants(null)).toEqual(0)
it 'returns zero when products list is empty', ->
expect(scope.countVariants([])).toEqual(0)
it 'adds order cycle suppliers', ->
scope.new_supplier_id = 'new supplier id'

View File

@@ -0,0 +1,29 @@
require "spec_helper"
describe ExchangeProductsRenderer do
let(:order_cycle) { create(:order_cycle) }
let(:coordinator) { order_cycle.coordinator }
let(:renderer) { described_class.new(order_cycle, coordinator.owner) }
describe "#exchange_products" do
describe "for an incoming exchange" do
it "loads products" do
exchange = order_cycle.exchanges.incoming.first
products = renderer.exchange_products(true, exchange.sender)
expect(products.first.supplier.name).to eq exchange.variants.first.product.supplier.name
end
end
describe "for an outgoing exchange" do
it "loads products" do
exchange = order_cycle.exchanges.outgoing.first
products = renderer.exchange_products(false, exchange.receiver)
suppliers = [exchange.variants[0].product.supplier.name, exchange.variants[1].product.supplier.name]
expect(suppliers).to include products.first.supplier.name
expect(suppliers).to include products.second.supplier.name
end
end
end
end