mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge pull request #2733 from kristinalim/fix-subscription_should_not_require_future_oc
Reduce restrictions for adding a variant to a subscription
This commit is contained in:
@@ -6,7 +6,11 @@ angular.module("admin.subscriptions").controller "SubscriptionController", ($sco
|
||||
$scope.schedules = Schedules.all
|
||||
$scope.paymentMethods = PaymentMethods.all
|
||||
$scope.shippingMethods = ShippingMethods.all
|
||||
$scope.distributor_id = $scope.subscription.shop_id # variant selector requires distributor_id
|
||||
|
||||
# Variant selector requires these
|
||||
$scope.distributor_id = $scope.subscription.shop_id
|
||||
$scope.eligible_for_subscriptions = true
|
||||
|
||||
$scope.view = if $scope.subscription.id? then 'review' else 'details'
|
||||
$scope.nextCallbacks = {}
|
||||
$scope.backCallbacks = {}
|
||||
|
||||
@@ -22,6 +22,7 @@ angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
|
||||
q: term
|
||||
distributor_id: scope.distributor_id
|
||||
order_cycle_id: scope.order_cycle_id
|
||||
eligible_for_subscriptions: scope.eligible_for_subscriptions
|
||||
results: (data, page) ->
|
||||
results: data
|
||||
formatResult: (variant) ->
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
@import '../variables';
|
||||
|
||||
.admin-subscription-form-subscription-line-items {
|
||||
.not-in-open-and-upcoming-order-cycles-warning {
|
||||
color: $warning-red;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
@import '../variables';
|
||||
|
||||
.admin-subscription-review-subscription-line-items {
|
||||
.not-in-open-and-upcoming-order-cycles-warning {
|
||||
color: $warning-red;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@ module Admin
|
||||
def build
|
||||
@subscription_line_item.assign_attributes(params[:subscription_line_item])
|
||||
@subscription_line_item.price_estimate = price_estimate
|
||||
render json: @subscription_line_item, serializer: Api::Admin::SubscriptionLineItemSerializer
|
||||
render json: @subscription_line_item, serializer: Api::Admin::SubscriptionLineItemSerializer,
|
||||
shop: @shop, schedule: @schedule
|
||||
end
|
||||
|
||||
private
|
||||
@@ -26,7 +27,7 @@ module Admin
|
||||
@shop = Enterprise.managed_by(spree_current_user).find_by_id(params[:shop_id])
|
||||
@schedule = permissions.editable_schedules.find_by_id(params[:schedule_id])
|
||||
@order_cycle = @schedule.andand.current_or_next_order_cycle
|
||||
@variant = Spree::Variant.stockable_by(@shop).find_by_id(params[:subscription_line_item][:variant_id])
|
||||
@variant = variant_if_eligible(params[:subscription_line_item][:variant_id]) if @shop.present?
|
||||
end
|
||||
|
||||
def new_actions
|
||||
@@ -50,5 +51,9 @@ module Admin
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@shop).scope(@variant)
|
||||
@variant.price + fee_calculator.indexed_fees_for(@variant)
|
||||
end
|
||||
|
||||
def variant_if_eligible(variant_id)
|
||||
SubscriptionVariantsService.eligible_variants(@shop).find_by_id(variant_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
module Api
|
||||
module Admin
|
||||
class SubscriptionLineItemSerializer < ActiveModel::Serializer
|
||||
attributes :id, :variant_id, :quantity, :description, :price_estimate
|
||||
attributes :id, :variant_id, :quantity, :description, :price_estimate,
|
||||
:in_open_and_upcoming_order_cycles
|
||||
|
||||
def description
|
||||
"#{object.variant.product.name} - #{object.variant.full_name}"
|
||||
@@ -10,6 +11,22 @@ module Api
|
||||
def price_estimate
|
||||
object.price_estimate.andand.to_f || "?"
|
||||
end
|
||||
|
||||
def in_open_and_upcoming_order_cycles
|
||||
SubscriptionVariantsService.in_open_and_upcoming_order_cycles?(option_or_assigned_shop,
|
||||
option_or_assigned_schedule,
|
||||
object.variant)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def option_or_assigned_shop
|
||||
@options[:shop] || object.subscription.andand.shop
|
||||
end
|
||||
|
||||
def option_or_assigned_schedule
|
||||
@options[:schedule] || object.subscription.andand.schedule
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -97,15 +97,12 @@ class SubscriptionValidator
|
||||
errors.add(:subscription_line_items, :not_available, name: name)
|
||||
end
|
||||
|
||||
# TODO: Extract this into a separate class
|
||||
def available_variant_ids
|
||||
@available_variant_ids ||=
|
||||
Spree::Variant.joins(exchanges: { order_cycle: :schedules })
|
||||
.where(id: subscription_line_items.map(&:variant_id))
|
||||
.where(schedules: { id: schedule }, exchanges: { incoming: false, receiver_id: shop })
|
||||
.merge(OrderCycle.not_closed)
|
||||
.select('DISTINCT spree_variants.id')
|
||||
.pluck(:id)
|
||||
return @available_variant_ids if @available_variant_ids.present?
|
||||
|
||||
subscription_variant_ids = subscription_line_items.map(&:variant_id)
|
||||
@available_variant_ids = SubscriptionVariantsService.eligible_variants(shop)
|
||||
.where(id: subscription_variant_ids).pluck(:id)
|
||||
end
|
||||
|
||||
def build_msg_from(k, msg)
|
||||
|
||||
39
app/services/subscription_variants_service.rb
Normal file
39
app/services/subscription_variants_service.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
class SubscriptionVariantsService
|
||||
# Includes the following variants:
|
||||
# - Variants of permitted producers
|
||||
# - Variants of hub
|
||||
# - Variants that are in outgoing exchanges where the hub is receiver
|
||||
def self.eligible_variants(distributor)
|
||||
variant_conditions = ["spree_products.supplier_id IN (?)", permitted_producer_ids(distributor)]
|
||||
exchange_variant_ids = outgoing_exchange_variant_ids(distributor)
|
||||
if exchange_variant_ids.present?
|
||||
variant_conditions[0] << " OR spree_variants.id IN (?)"
|
||||
variant_conditions << exchange_variant_ids
|
||||
end
|
||||
|
||||
Spree::Variant.joins(:product).where(is_master: false).where(*variant_conditions)
|
||||
end
|
||||
|
||||
def self.in_open_and_upcoming_order_cycles?(distributor, schedule, variant)
|
||||
scope = ExchangeVariant.joins(exchange: { order_cycle: :schedules })
|
||||
.where(variant_id: variant, exchanges: { incoming: false, receiver_id: distributor })
|
||||
.merge(OrderCycle.not_closed)
|
||||
scope = scope.where(schedules: { id: schedule })
|
||||
scope.any?
|
||||
end
|
||||
|
||||
def self.permitted_producer_ids(distributor)
|
||||
other_permitted_producer_ids = EnterpriseRelationship.joins(:parent)
|
||||
.permitting(distributor).with_permission(:add_to_order_cycle)
|
||||
.merge(Enterprise.is_primary_producer)
|
||||
.pluck(:parent_id)
|
||||
|
||||
other_permitted_producer_ids | [distributor.id]
|
||||
end
|
||||
|
||||
def self.outgoing_exchange_variant_ids(distributor)
|
||||
ExchangeVariant.select("DISTINCT exchange_variants.variant_id").joins(:exchange)
|
||||
.where(exchanges: { incoming: false, receiver_id: distributor.id })
|
||||
.pluck(:variant_id)
|
||||
end
|
||||
end
|
||||
@@ -56,7 +56,7 @@
|
||||
%input#edit-products{ type: "button", value: t(:edit), ng: { click: "setView('products')" } }
|
||||
.row
|
||||
.seven.columns.alpha.omega
|
||||
%table#subscription-line-items
|
||||
%table#subscription-line-items.admin-subscription-review-subscription-line-items
|
||||
%colgroup
|
||||
%col{:style => "width: 62%;"}/
|
||||
%col{:style => "width: 14%;"}/
|
||||
@@ -71,7 +71,10 @@
|
||||
%span= t(:total)
|
||||
%tbody
|
||||
%tr.item{ id: "sli_{{$index}}", ng: { repeat: "item in subscription.subscription_line_items | filter:{ _destroy: '!true' }", class: { even: 'even', odd: 'odd' } } }
|
||||
%td.description {{ item.description }}
|
||||
%td
|
||||
.description {{ item.description }}
|
||||
.not-in-open-and-upcoming-order-cycles-warning{ ng: { if: '!item.in_open_and_upcoming_order_cycles' } }
|
||||
= t(".no_open_or_upcoming_order_cycle")
|
||||
%td.price.align-center {{ item.price_estimate | currency }}
|
||||
%td.quantity {{ item.quantity }}
|
||||
%td.total.align-center {{ (item.price_estimate * item.quantity) | currency }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%table#subscription-line-items
|
||||
%table#subscription-line-items.admin-subscription-form-subscription-line-items
|
||||
%colgroup
|
||||
%col{:style => "width: 49%;"}/
|
||||
%col{:style => "width: 14%;"}/
|
||||
@@ -15,7 +15,10 @@
|
||||
%th.orders-actions.actions
|
||||
%tbody
|
||||
%tr.item{ id: "sli_{{$index}}", ng: { repeat: "item in subscription.subscription_line_items | filter:{ _destroy: '!true' }", class: { even: 'even', odd: 'odd' } } }
|
||||
%td.description {{ item.description }}
|
||||
%td
|
||||
.description {{ item.description }}
|
||||
.not-in-open-and-upcoming-order-cycles-warning{ ng: { if: '!item.in_open_and_upcoming_order_cycles' } }
|
||||
= t(".not_in_open_and_upcoming_order_cycles_warning")
|
||||
%td.price.align-center {{ item.price_estimate | currency }}
|
||||
%td.quantity
|
||||
%input{ name: 'quantity', type: 'number', min: 0, ng: { model: 'item.quantity' } }
|
||||
|
||||
@@ -1088,6 +1088,7 @@ en:
|
||||
this_is_an_estimate: |
|
||||
The displayed prices are only an estimate and calculated at the time the subscription is changed.
|
||||
If you change prices or fees, orders will be updated, but the subscription will still display the old values.
|
||||
not_in_open_and_upcoming_order_cycles_warning: "There are no open or upcoming order cycles for this product."
|
||||
details:
|
||||
details: Details
|
||||
invalid_error: Oops! Please fill in all of the required fields...
|
||||
@@ -1102,6 +1103,7 @@ en:
|
||||
details: Details
|
||||
address: Address
|
||||
products: Products
|
||||
no_open_or_upcoming_order_cycle: "No Upcoming Order Cycle"
|
||||
product_already_in_order: This product has already been added to the order. Please edit the quantity directly.
|
||||
orders:
|
||||
number: Number
|
||||
|
||||
@@ -33,6 +33,10 @@ module OpenFoodNetwork
|
||||
Spree::Variant.where(is_master: false).ransack(search_params.merge(m: 'or')).result
|
||||
end
|
||||
|
||||
def distributor
|
||||
Enterprise.find params[:distributor_id]
|
||||
end
|
||||
|
||||
def scope_to_schedule
|
||||
@variants = @variants.in_schedule(params[:schedule_id])
|
||||
end
|
||||
@@ -42,12 +46,29 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def scope_to_distributor
|
||||
distributor = Enterprise.find params[:distributor_id]
|
||||
if params[:eligible_for_subscriptions]
|
||||
scope_to_eligible_for_subscriptions_in_distributor
|
||||
else
|
||||
scope_to_available_for_orders_in_distributor
|
||||
end
|
||||
end
|
||||
|
||||
def scope_to_available_for_orders_in_distributor
|
||||
@variants = @variants.in_distributor(distributor)
|
||||
scope_variants_to_distributor(@variants, distributor)
|
||||
end
|
||||
|
||||
def scope_to_eligible_for_subscriptions_in_distributor
|
||||
eligible_variants_scope = SubscriptionVariantsService.eligible_variants(distributor)
|
||||
@variants = @variants.merge(eligible_variants_scope)
|
||||
scope_variants_to_distributor(@variants, distributor)
|
||||
end
|
||||
|
||||
def scope_variants_to_distributor(variants, distributor)
|
||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||
# Perform scoping after all filtering is done.
|
||||
# Filtering could be a problem on scoped variants.
|
||||
@variants.each { |v| scoper.scope(v) }
|
||||
variants.each { |v| scoper.scope(v) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,9 +10,9 @@ describe Admin::SubscriptionLineItemsController, type: :controller do
|
||||
let(:unmanaged_shop) { create(:enterprise) }
|
||||
let!(:product) { create(:product) }
|
||||
let!(:variant) { create(:variant, product: product, unit_value: '100', price: 15.00, option_values: []) }
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: shop, receiver: shop, variants: [variant], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:enterprise_fee) { create(:enterprise_fee, amount: 3.50) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.days.from_now, orders_close_at: 7.days.from_now) }
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: shop, receiver: shop, variants: [variant], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let(:unmanaged_schedule) { create(:schedule, order_cycles: [create(:simple_order_cycle, coordinator: unmanaged_shop)]) }
|
||||
|
||||
@@ -42,6 +42,8 @@ describe Admin::SubscriptionLineItemsController, type: :controller do
|
||||
before { params.merge!(shop_id: shop.id) }
|
||||
|
||||
context "but the shop doesn't have permission to sell product in question" do
|
||||
let!(:outgoing_exchange) { }
|
||||
|
||||
it "returns an error" do
|
||||
spree_post :build, params
|
||||
json_response = JSON.parse(response.body)
|
||||
|
||||
@@ -341,7 +341,7 @@ describe Admin::SubscriptionsController, type: :controller do
|
||||
end
|
||||
|
||||
context 'with subscription_line_items params' do
|
||||
let!(:product2) { create(:product, supplier: shop) }
|
||||
let!(:product2) { create(:product) }
|
||||
let!(:variant2) { create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: []) }
|
||||
|
||||
before do
|
||||
|
||||
@@ -145,23 +145,25 @@ feature 'Subscriptions' do
|
||||
let!(:customer_user) { create(:user) }
|
||||
let!(:credit_card1) { create(:credit_card, user: customer_user, cc_type: 'visa', last_digits: 1111, month: 10, year: 2030) }
|
||||
let!(:customer) { create(:customer, enterprise: shop, bill_address: address, user: customer_user, allow_charges: true) }
|
||||
let!(:product1) { create(:product, supplier: shop) }
|
||||
let!(:product2) { create(:product, supplier: shop) }
|
||||
let!(:variant1) { create(:variant, product: product1, unit_value: '100', price: 12.00, option_values: []) }
|
||||
let!(:variant2) { create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: []) }
|
||||
let!(:test_product) { create(:product, supplier: shop, distributors: []) }
|
||||
let!(:test_variant) { create(:variant, product: test_product, unit_value: "100", price: 12.00, option_values: []) }
|
||||
let!(:shop_product) { create(:product, supplier: shop, distributors: [shop]) }
|
||||
let!(:shop_variant) { create(:variant, product: shop_product, unit_value: "1000", price: 6.00, option_values: []) }
|
||||
let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.days.from_now, orders_close_at: 7.days.from_now) }
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant2], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: shop, receiver: shop, variants: [test_variant, shop_variant], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let!(:payment_method) { create(:stripe_payment_method, name: 'Credit Card', distributors: [shop], preferred_enterprise_id: shop.id) }
|
||||
let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
|
||||
|
||||
it "passes the smoke test" do
|
||||
before do
|
||||
visit admin_subscriptions_path
|
||||
click_link 'New Subscription'
|
||||
select2_select shop.name, from: 'new_subscription_shop_id'
|
||||
click_button 'Continue'
|
||||
click_link "New Subscription"
|
||||
select2_select shop.name, from: "new_subscription_shop_id"
|
||||
click_button "Continue"
|
||||
end
|
||||
|
||||
it "passes the smoke test" do
|
||||
select2_select customer.email, from: 'customer_id'
|
||||
select2_select schedule.name, from: 'schedule_id'
|
||||
select2_select payment_method.name, from: 'payment_method_id'
|
||||
@@ -215,11 +217,9 @@ feature 'Subscriptions' do
|
||||
expect(page).to have_content 'Please add at least one product'
|
||||
|
||||
# Adding a product and getting a price estimate
|
||||
select2_search_async product1.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop'
|
||||
fill_in 'add_quantity', with: 2
|
||||
click_link 'Add'
|
||||
add_variant_to_subscription test_variant, 2
|
||||
within 'table#subscription-line-items tr.item', match: :first do
|
||||
expect(page).to have_selector 'td.description', text: "#{product1.name} - #{variant1.full_name}"
|
||||
expect(page).to have_selector '.description', text: "#{test_product.name} - #{test_variant.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$13.75"
|
||||
expect(page).to have_input 'quantity', with: "2"
|
||||
expect(page).to have_selector 'td.total', text: "$27.50"
|
||||
@@ -241,11 +241,9 @@ feature 'Subscriptions' do
|
||||
click_button('edit-products')
|
||||
|
||||
# Adding a new product
|
||||
select2_search_async product2.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop'
|
||||
fill_in 'add_quantity', with: 3
|
||||
click_link 'Add'
|
||||
add_variant_to_subscription shop_variant, 3
|
||||
within 'table#subscription-line-items tr.item', match: :first do
|
||||
expect(page).to have_selector 'td.description', text: "#{product2.name} - #{variant2.full_name}"
|
||||
expect(page).to have_selector '.description', text: "#{shop_product.name} - #{shop_variant.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$7.75"
|
||||
expect(page).to have_input 'quantity', with: "3"
|
||||
expect(page).to have_selector 'td.total', text: "$23.25"
|
||||
@@ -264,7 +262,7 @@ feature 'Subscriptions' do
|
||||
|
||||
# Prices are shown in the index
|
||||
within 'table#subscription-line-items tr.item', match: :first do
|
||||
expect(page).to have_selector 'td.description', text: "#{product2.name} - #{variant2.full_name}"
|
||||
expect(page).to have_selector '.description', text: "#{shop_product.name} - #{shop_variant.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$7.75"
|
||||
expect(page).to have_input 'quantity', with: "3"
|
||||
expect(page).to have_selector 'td.total', text: "$23.25"
|
||||
@@ -282,142 +280,249 @@ feature 'Subscriptions' do
|
||||
# Standing Line Items are created
|
||||
expect(subscription.subscription_line_items.count).to eq 1
|
||||
subscription_line_item = subscription.subscription_line_items.first
|
||||
expect(subscription_line_item.variant).to eq variant2
|
||||
expect(subscription_line_item.variant).to eq shop_variant
|
||||
expect(subscription_line_item.quantity).to eq 3
|
||||
end
|
||||
end
|
||||
|
||||
context 'editing an existing subscription' do
|
||||
let!(:customer) { create(:customer, enterprise: shop) }
|
||||
let!(:product1) { create(:product, supplier: shop) }
|
||||
let!(:product2) { create(:product, supplier: shop) }
|
||||
let!(:product3) { create(:product, supplier: shop) }
|
||||
let!(:variant1) { create(:variant, product: product1, unit_value: '100', price: 12.00, option_values: []) }
|
||||
let!(:variant2) { create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: []) }
|
||||
let!(:variant3) { create(:variant, product: product3, unit_value: '10000', price: 22.00, option_values: []) }
|
||||
let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.days.from_now, orders_close_at: 7.days.from_now) }
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant2], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let!(:variant3_oc) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.days.from_now, orders_close_at: 7.days.from_now) }
|
||||
let!(:variant3_ex) { variant3_oc.exchanges.create(sender: shop, receiver: shop, variants: [variant3]) }
|
||||
let!(:payment_method) { create(:payment_method, distributors: [shop]) }
|
||||
let!(:stripe_payment_method) { create(:stripe_payment_method, name: 'Credit Card', distributors: [shop], preferred_enterprise_id: shop.id) }
|
||||
let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
|
||||
let!(:subscription) {
|
||||
create(:subscription,
|
||||
shop: shop,
|
||||
customer: customer,
|
||||
schedule: schedule,
|
||||
payment_method: payment_method,
|
||||
shipping_method: shipping_method,
|
||||
subscription_line_items: [create(:subscription_line_item, variant: variant1, quantity: 2, price_estimate: 13.75)],
|
||||
with_proxy_orders: true)
|
||||
}
|
||||
context 'editing an existing subscription' do
|
||||
let!(:customer) { create(:customer, enterprise: shop) }
|
||||
let!(:product1) { create(:product, supplier: shop) }
|
||||
let!(:product2) { create(:product, supplier: shop) }
|
||||
let!(:product3) { create(:product, supplier: shop) }
|
||||
let!(:variant1) { create(:variant, product: product1, unit_value: '100', price: 12.00, option_values: []) }
|
||||
let!(:variant2) { create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: []) }
|
||||
let!(:variant3) { create(:variant, product: product3, unit_value: '10000', price: 22.00, option_values: []) }
|
||||
let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.days.from_now, orders_close_at: 7.days.from_now) }
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant2], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let!(:variant3_oc) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.days.from_now, orders_close_at: 7.days.from_now) }
|
||||
let!(:variant3_ex) { variant3_oc.exchanges.create(sender: shop, receiver: shop, variants: [variant3]) }
|
||||
let!(:payment_method) { create(:payment_method, distributors: [shop]) }
|
||||
let!(:stripe_payment_method) { create(:stripe_payment_method, name: 'Credit Card', distributors: [shop], preferred_enterprise_id: shop.id) }
|
||||
let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
|
||||
let!(:subscription) {
|
||||
create(:subscription,
|
||||
shop: shop,
|
||||
customer: customer,
|
||||
schedule: schedule,
|
||||
payment_method: payment_method,
|
||||
shipping_method: shipping_method,
|
||||
subscription_line_items: [create(:subscription_line_item, variant: variant1, quantity: 2, price_estimate: 13.75)],
|
||||
with_proxy_orders: true)
|
||||
}
|
||||
|
||||
it "passes the smoke test" do
|
||||
visit edit_admin_subscription_path(subscription)
|
||||
it "passes the smoke test" do
|
||||
visit edit_admin_subscription_path(subscription)
|
||||
|
||||
# Customer and Schedule cannot be edited
|
||||
click_button 'edit-details'
|
||||
expect(page).to have_selector '#s2id_customer_id.select2-container-disabled'
|
||||
expect(page).to have_selector '#s2id_schedule_id.select2-container-disabled'
|
||||
# Customer and Schedule cannot be edited
|
||||
click_button 'edit-details'
|
||||
expect(page).to have_selector '#s2id_customer_id.select2-container-disabled'
|
||||
expect(page).to have_selector '#s2id_schedule_id.select2-container-disabled'
|
||||
|
||||
# Can't use a Stripe payment method because customer does not allow it
|
||||
select2_select stripe_payment_method.name, from: 'payment_method_id'
|
||||
expect(page).to have_content I18n.t('admin.subscriptions.details.charges_not_allowed')
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_content 'Credit card charges are not allowed by this customer'
|
||||
select2_select payment_method.name, from: 'payment_method_id'
|
||||
click_button 'Review'
|
||||
# Can't use a Stripe payment method because customer does not allow it
|
||||
select2_select stripe_payment_method.name, from: 'payment_method_id'
|
||||
expect(page).to have_content I18n.t('admin.subscriptions.details.charges_not_allowed')
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_content 'Credit card charges are not allowed by this customer'
|
||||
select2_select payment_method.name, from: 'payment_method_id'
|
||||
click_button 'Review'
|
||||
|
||||
# Existing products should be visible
|
||||
click_button 'edit-products'
|
||||
within "#sli_0" do
|
||||
expect(page).to have_selector 'td.description', text: "#{product1.name} - #{variant1.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$13.75"
|
||||
expect(page).to have_input 'quantity', with: "2"
|
||||
expect(page).to have_selector 'td.total', text: "$27.50"
|
||||
# Existing products should be visible
|
||||
click_button 'edit-products'
|
||||
within "#sli_0" do
|
||||
expect(page).to have_selector '.description', text: "#{product1.name} - #{variant1.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$13.75"
|
||||
expect(page).to have_input 'quantity', with: "2"
|
||||
expect(page).to have_selector 'td.total', text: "$27.50"
|
||||
|
||||
# Remove variant1 from the subscription
|
||||
find("a.delete-item").click
|
||||
end
|
||||
|
||||
# Attempting to submit without a product
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_content 'Please add at least one product'
|
||||
|
||||
# Add variant2 to the subscription
|
||||
select2_search_async product2.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop'
|
||||
fill_in 'add_quantity', with: 1
|
||||
click_link 'Add'
|
||||
within "#sli_0" do
|
||||
expect(page).to have_selector 'td.description', text: "#{product2.name} - #{variant2.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$7.75"
|
||||
expect(page).to have_input 'quantity', with: "1"
|
||||
expect(page).to have_selector 'td.total', text: "$7.75"
|
||||
end
|
||||
|
||||
# Total should be $7.75
|
||||
expect(page).to have_selector '#order_form_total', text: "$7.75"
|
||||
|
||||
# Add variant3 to the subscription (even though it is not available)
|
||||
select2_search_async product3.name, from: I18n.t(:name_or_sku), dropdown_css: '.select2-drop'
|
||||
fill_in 'add_quantity', with: 1
|
||||
click_link 'Add'
|
||||
within "#sli_1" do
|
||||
expect(page).to have_selector 'td.description', text: "#{product3.name} - #{variant3.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$22.00"
|
||||
expect(page).to have_input 'quantity', with: "1"
|
||||
expect(page).to have_selector 'td.total', text: "$22.00"
|
||||
end
|
||||
|
||||
# Total should be $29.75
|
||||
expect(page).to have_selector '#order_form_total', text: "$29.75"
|
||||
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_content "#{product3.name} - #{variant3.full_name} is not available from the selected schedule"
|
||||
|
||||
# Remove variant3 from the subscription
|
||||
within '#sli_1' do
|
||||
find("a.delete-item").click
|
||||
end
|
||||
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_current_path admin_subscriptions_path
|
||||
|
||||
select2_select shop.name, from: "shop_id"
|
||||
expect(page).to have_selector "td.items.panel-toggle"
|
||||
first("td.items.panel-toggle").click
|
||||
|
||||
# Total should be $7.75
|
||||
expect(page).to have_selector '#order_form_total', text: "$7.75"
|
||||
expect(page).to have_selector 'tr.item', count: 1
|
||||
expect(subscription.reload.subscription_line_items.length).to eq 1
|
||||
expect(subscription.subscription_line_items.first.variant).to eq variant2
|
||||
# Remove variant1 from the subscription
|
||||
find("a.delete-item").click
|
||||
end
|
||||
|
||||
context "with initialised order that has been changed" do
|
||||
let(:proxy_order) { subscription.proxy_orders.first }
|
||||
let(:order) { proxy_order.initialise_order! }
|
||||
let(:line_item) { order.line_items.first }
|
||||
# Attempting to submit without a product
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_content 'Please add at least one product'
|
||||
|
||||
before { line_item.update_attributes(quantity: 3) }
|
||||
# Add variant2 to the subscription
|
||||
add_variant_to_subscription(variant2, 1)
|
||||
within "#sli_0" do
|
||||
expect(page).to have_selector '.description', text: "#{product2.name} - #{variant2.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$7.75"
|
||||
expect(page).to have_input 'quantity', with: "1"
|
||||
expect(page).to have_selector 'td.total', text: "$7.75"
|
||||
end
|
||||
|
||||
it "reports issues encountered during the update" do
|
||||
visit edit_admin_subscription_path(subscription)
|
||||
click_button 'edit-products'
|
||||
# Total should be $7.75
|
||||
expect(page).to have_selector '#order_form_total', text: "$7.75"
|
||||
|
||||
within "#sli_0" do
|
||||
fill_in 'quantity', with: "1"
|
||||
end
|
||||
# Add variant3 to the subscription (even though it is not available)
|
||||
add_variant_to_subscription(variant3, 1)
|
||||
within "#sli_1" do
|
||||
expect(page).to have_selector '.description', text: "#{product3.name} - #{variant3.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$22.00"
|
||||
expect(page).to have_input 'quantity', with: "1"
|
||||
expect(page).to have_selector 'td.total', text: "$22.00"
|
||||
end
|
||||
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_content 'Saved'
|
||||
# Total should be $29.75
|
||||
expect(page).to have_selector '#order_form_total', text: "$29.75"
|
||||
|
||||
expect(page).to have_selector "#order_update_issues_dialog .message", text: I18n.t("admin.subscriptions.order_update_issues_msg")
|
||||
# Remove variant3 from the subscription
|
||||
within '#sli_1' do
|
||||
find("a.delete-item").click
|
||||
end
|
||||
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_current_path admin_subscriptions_path
|
||||
|
||||
select2_select shop.name, from: "shop_id"
|
||||
expect(page).to have_selector "td.items.panel-toggle"
|
||||
first("td.items.panel-toggle").click
|
||||
|
||||
# Total should be $7.75
|
||||
expect(page).to have_selector '#order_form_total', text: "$7.75"
|
||||
expect(page).to have_selector 'tr.item', count: 1
|
||||
expect(subscription.reload.subscription_line_items.length).to eq 1
|
||||
expect(subscription.subscription_line_items.first.variant).to eq variant2
|
||||
end
|
||||
|
||||
context "with initialised order that has been changed" do
|
||||
let(:proxy_order) { subscription.proxy_orders.first }
|
||||
let(:order) { proxy_order.initialise_order! }
|
||||
let(:line_item) { order.line_items.first }
|
||||
|
||||
before { line_item.update_attributes(quantity: 3) }
|
||||
|
||||
it "reports issues encountered during the update" do
|
||||
visit edit_admin_subscription_path(subscription)
|
||||
click_button 'edit-products'
|
||||
|
||||
within "#sli_0" do
|
||||
fill_in 'quantity', with: "1"
|
||||
end
|
||||
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_content 'Saved'
|
||||
|
||||
expect(page).to have_selector "#order_update_issues_dialog .message", text: I18n.t("admin.subscriptions.order_update_issues_msg")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "allowed variants" do
|
||||
let!(:customer) { create(:customer, enterprise: shop, allow_charges: true) }
|
||||
let!(:credit_card) { create(:credit_card, user: customer.user) }
|
||||
let!(:shop_product) { create(:product, supplier: shop, distributors: [shop]) }
|
||||
let!(:shop_variant) { create(:variant, product: shop_product, unit_value: "2000") }
|
||||
let!(:permitted_supplier) do
|
||||
create(:supplier_enterprise).tap do |supplier|
|
||||
create(:enterprise_relationship, child: shop, parent: supplier, permissions_list: [:add_to_order_cycle])
|
||||
end
|
||||
end
|
||||
let!(:permitted_supplier_product) { create(:product, supplier: permitted_supplier, distributors: [shop]) }
|
||||
let!(:permitted_supplier_variant) { create(:variant, product: permitted_supplier_product, unit_value: "2000") }
|
||||
let!(:incoming_exchange_product) { create(:product, distributors: [shop]) }
|
||||
let!(:incoming_exchange_variant) do
|
||||
create(:variant, product: incoming_exchange_product, unit_value: "2000").tap do |variant|
|
||||
create(:exchange, order_cycle: order_cycle, incoming: true, receiver: shop, variants: [variant])
|
||||
end
|
||||
end
|
||||
let!(:outgoing_exchange_product) { create(:product, distributors: [shop]) }
|
||||
let!(:outgoing_exchange_variant) do
|
||||
create(:variant, product: outgoing_exchange_product, unit_value: "2000").tap do |variant|
|
||||
create(:exchange, order_cycle: order_cycle, incoming: false, receiver: shop, variants: [variant])
|
||||
end
|
||||
end
|
||||
let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let!(:payment_method) { create(:stripe_payment_method, distributors: [shop], preferred_enterprise_id: shop.id) }
|
||||
let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
|
||||
|
||||
before do
|
||||
visit admin_subscriptions_path
|
||||
click_link "New Subscription"
|
||||
select2_select shop.name, from: "new_subscription_shop_id"
|
||||
click_button "Continue"
|
||||
end
|
||||
|
||||
it "permit creating and editing of the subscription" do
|
||||
# Fill in other details
|
||||
fill_in_subscription_basic_details
|
||||
click_button "Next"
|
||||
expect(page).to have_content "BILLING ADDRESS"
|
||||
click_button "Next"
|
||||
|
||||
# Add products
|
||||
expect(page).to have_content "NAME OR SKU"
|
||||
add_variant_to_subscription shop_variant, 3
|
||||
expect_not_in_open_or_upcoming_order_cycle_warning 1
|
||||
add_variant_to_subscription permitted_supplier_variant, 4
|
||||
expect_not_in_open_or_upcoming_order_cycle_warning 2
|
||||
add_variant_to_subscription incoming_exchange_variant, 5
|
||||
expect_not_in_open_or_upcoming_order_cycle_warning 3
|
||||
add_variant_to_subscription outgoing_exchange_variant, 6
|
||||
expect_not_in_open_or_upcoming_order_cycle_warning 3
|
||||
click_button "Next"
|
||||
|
||||
# Submit form
|
||||
expect {
|
||||
click_button "Create Subscription"
|
||||
expect(page).to have_current_path admin_subscriptions_path
|
||||
}.to change(Subscription, :count).by(1)
|
||||
|
||||
# Subscription line items are created
|
||||
subscription = Subscription.last
|
||||
expect(subscription.subscription_line_items.count).to eq 4
|
||||
|
||||
# Edit the subscription
|
||||
visit edit_admin_subscription_path(subscription)
|
||||
|
||||
# Remove shop_variant from the subscription
|
||||
click_button "edit-products"
|
||||
within "#sli_0" do
|
||||
expect(page).to have_selector ".description", text: shop_variant.name
|
||||
find("a.delete-item").click
|
||||
end
|
||||
|
||||
# Submit form
|
||||
click_button "Save Changes"
|
||||
expect(page).to have_current_path admin_subscriptions_path
|
||||
|
||||
# Subscription is saved
|
||||
visit edit_admin_subscription_path(subscription)
|
||||
expect(page).to have_selector "#subscription-line-items .item", count: 3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def fill_in_subscription_basic_details
|
||||
select2_select customer.email, from: "customer_id"
|
||||
select2_select schedule.name, from: "schedule_id"
|
||||
select2_select payment_method.name, from: "payment_method_id"
|
||||
select2_select shipping_method.name, from: "shipping_method_id"
|
||||
|
||||
find_field("begins_at").click
|
||||
choose_today_from_datepicker
|
||||
end
|
||||
|
||||
def expect_not_in_open_or_upcoming_order_cycle_warning(count)
|
||||
expect(page).to have_content variant_not_in_open_or_upcoming_order_cycle_warning, count: count
|
||||
end
|
||||
|
||||
def add_variant_to_subscription(variant, quantity)
|
||||
row_count = all("#subscription-line-items .item").length
|
||||
variant_name = variant.full_name.present? ? "#{variant.name} - #{variant.full_name}" : variant.name
|
||||
select2_search variant.name, from: I18n.t(:name_or_sku), dropdown_css: ".select2-drop", select_text: variant_name
|
||||
fill_in "add_quantity", with: quantity
|
||||
click_link "Add"
|
||||
expect(page).to have_selector("#subscription-line-items .item", count: row_count + 1)
|
||||
end
|
||||
|
||||
def variant_not_in_open_or_upcoming_order_cycle_warning
|
||||
I18n.t("not_in_open_and_upcoming_order_cycles_warning",
|
||||
scope: "admin.subscriptions.subscription_line_items")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
require "spec_helper"
|
||||
|
||||
describe SubscriptionValidator do
|
||||
let(:shop) { instance_double(Enterprise, name: "Shop") }
|
||||
let(:owner) { create(:user) }
|
||||
let(:shop) { create(:enterprise, name: "Shop", owner: owner) }
|
||||
|
||||
describe "delegation" do
|
||||
let(:subscription) { create(:subscription) }
|
||||
let(:subscription) { create(:subscription, shop: shop) }
|
||||
let(:validator) { SubscriptionValidator.new(subscription) }
|
||||
|
||||
it "delegates to subscription" do
|
||||
@@ -438,6 +441,7 @@ describe SubscriptionValidator do
|
||||
|
||||
context "but some variants are unavailable" do
|
||||
let(:product) { instance_double(Spree::Product, name: "some_name") }
|
||||
|
||||
before do
|
||||
allow(validator).to receive(:available_variant_ids) { [variant2.id] }
|
||||
allow(variant1).to receive(:product) { product }
|
||||
@@ -451,7 +455,9 @@ describe SubscriptionValidator do
|
||||
end
|
||||
|
||||
context "and all requested variants are available" do
|
||||
before { allow(validator).to receive(:available_variant_ids) { [variant1.id, variant2.id] } }
|
||||
before do
|
||||
allow(validator).to receive(:available_variant_ids) { [variant1.id, variant2.id] }
|
||||
end
|
||||
|
||||
it "returns true" do
|
||||
expect(validator.valid?).to be true
|
||||
|
||||
130
spec/services/subscription_variants_service_spec.rb
Normal file
130
spec/services/subscription_variants_service_spec.rb
Normal file
@@ -0,0 +1,130 @@
|
||||
require "spec_helper"
|
||||
|
||||
describe SubscriptionVariantsService do
|
||||
describe "variant eligibility for subscription" do
|
||||
let!(:shop) { create(:distributor_enterprise) }
|
||||
let!(:producer) { create(:supplier_enterprise) }
|
||||
let!(:product) { create(:product, supplier: producer) }
|
||||
let!(:variant) { product.variants.first }
|
||||
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let!(:subscription) { create(:subscription, shop: shop, schedule: schedule) }
|
||||
let!(:subscription_line_item) do
|
||||
create(:subscription_line_item, subscription: subscription, variant: variant)
|
||||
end
|
||||
|
||||
let(:current_order_cycle) do
|
||||
create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.ago,
|
||||
orders_close_at: 1.week.from_now)
|
||||
end
|
||||
|
||||
let(:future_order_cycle) do
|
||||
create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.from_now,
|
||||
orders_close_at: 2.weeks.from_now)
|
||||
end
|
||||
|
||||
let(:past_order_cycle) do
|
||||
create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.weeks.ago,
|
||||
orders_close_at: 1.week.ago)
|
||||
end
|
||||
|
||||
let!(:order_cycle) { current_order_cycle }
|
||||
|
||||
context "if the shop is the supplier for the product" do
|
||||
let!(:producer) { shop }
|
||||
|
||||
it "is eligible" do
|
||||
expect(described_class.eligible_variants(shop)).to include(variant)
|
||||
end
|
||||
end
|
||||
|
||||
context "if the supplier is permitted for the shop" do
|
||||
let!(:enterprise_relationship) { create(:enterprise_relationship, child: shop, parent: product.supplier, permissions_list: [:add_to_order_cycle]) }
|
||||
|
||||
it "is eligible" do
|
||||
expect(described_class.eligible_variants(shop)).to include(variant)
|
||||
end
|
||||
end
|
||||
|
||||
context "if the variant is involved in an exchange" do
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
|
||||
context "if it is an incoming exchange where the shop is the receiver" do
|
||||
let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) }
|
||||
|
||||
it "is not eligible" do
|
||||
expect(described_class.eligible_variants(shop)).to_not include(variant)
|
||||
end
|
||||
end
|
||||
|
||||
context "if it is an outgoing exchange where the shop is the receiver" do
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) }
|
||||
|
||||
context "if the order cycle is currently open" do
|
||||
let!(:order_cycle) { current_order_cycle }
|
||||
|
||||
it "is eligible" do
|
||||
expect(described_class.eligible_variants(shop)).to include(variant)
|
||||
end
|
||||
end
|
||||
|
||||
context "if the order cycle opens in the future" do
|
||||
let!(:order_cycle) { future_order_cycle }
|
||||
|
||||
it "is eligible" do
|
||||
expect(described_class.eligible_variants(shop)).to include(variant)
|
||||
end
|
||||
end
|
||||
|
||||
context "if the order cycle closed in the past" do
|
||||
let!(:order_cycle) { past_order_cycle }
|
||||
|
||||
it "is eligible" do
|
||||
expect(described_class.eligible_variants(shop)).to include(variant)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "if the variant is unrelated" do
|
||||
it "is not eligible" do
|
||||
expect(described_class.eligible_variants(shop)).to_not include(variant)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "checking if variant in open and upcoming order cycles" do
|
||||
let!(:shop) { create(:enterprise) }
|
||||
let!(:product) { create(:product) }
|
||||
let!(:variant) { product.variants.first }
|
||||
let!(:schedule) { create(:schedule) }
|
||||
|
||||
context "if the variant is involved in an exchange" do
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
|
||||
context "if it is an incoming exchange where the shop is the receiver" do
|
||||
let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) }
|
||||
|
||||
it "is is false" do
|
||||
expect(described_class).not_to be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
|
||||
end
|
||||
end
|
||||
|
||||
context "if it is an outgoing exchange where the shop is the receiver" do
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) }
|
||||
|
||||
it "is true" do
|
||||
expect(described_class).to be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "if the variant is unrelated" do
|
||||
it "is false" do
|
||||
expect(described_class).to_not be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -136,6 +136,7 @@ RSpec.configure do |config|
|
||||
config.extend Spree::Api::TestingSupport::Setup, :type => :controller
|
||||
config.include Spree::Api::TestingSupport::Helpers, :type => :controller
|
||||
config.include OpenFoodNetwork::ControllerHelper, :type => :controller
|
||||
config.include Features::DatepickerHelper, type: :feature
|
||||
config.include OpenFoodNetwork::FeatureToggleHelper
|
||||
config.include OpenFoodNetwork::FiltersHelper
|
||||
config.include OpenFoodNetwork::EnterpriseGroupsHelper
|
||||
|
||||
9
spec/support/features/datepicker_helper.rb
Normal file
9
spec/support/features/datepicker_helper.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
module Features
|
||||
module DatepickerHelper
|
||||
def choose_today_from_datepicker
|
||||
within(".ui-datepicker-calendar") do
|
||||
find(".ui-datepicker-today").click
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -105,6 +105,16 @@ module WebHelper
|
||||
targetted_select2(value, options)
|
||||
end
|
||||
|
||||
# Support having different texts to search for and to click in the select2
|
||||
# field.
|
||||
#
|
||||
# This overrides the method in Spree.
|
||||
def targetted_select2_search(value, options)
|
||||
page.execute_script %Q{$('#{options[:from]}').select2('open')}
|
||||
page.execute_script "$('#{options[:dropdown_css]} input.select2-input').val('#{value}').trigger('keyup-change');"
|
||||
select_select2_result(options[:select_text] || value)
|
||||
end
|
||||
|
||||
def multi_select2_select(value, options)
|
||||
find("#s2id_#{options[:from]}").find('ul li.select2-search-field').click
|
||||
select_select2_result(value)
|
||||
|
||||
Reference in New Issue
Block a user