Merge tag 'v1.8.10' into transifex

This commit is contained in:
Maikel Linke
2017-05-05 12:28:16 +10:00
34 changed files with 284 additions and 59 deletions

View File

@@ -1,3 +1,6 @@
See this here post on raising a github issue:
https://community.openfoodnetwork.org/t/how-to-raise-a-github-issue/912
# Contributing
We love pull requests from everyone. Here are some instructions for

View File

@@ -643,9 +643,8 @@ GEM
whenever (0.9.2)
activesupport (>= 2.3.4)
chronic (>= 0.6.3)
wicked_pdf (0.11.0)
rails
wkhtmltopdf-binary (0.9.9.3)
wicked_pdf (1.1.0)
wkhtmltopdf-binary (0.12.3.1)
xml-simple (1.1.4)
xpath (2.0.0)
nokogiri (~> 1.3)

View File

@@ -98,6 +98,14 @@ The site is configured to use
startup time while Rails loads. See the Zeus github page for
usage instructions.
Once [npm dependencies are
installed](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Karma), AngularJS tests can be run with:
./script/karma run
If you want karma to automatically rerun the tests on file modification, use:
./script/karma start
## Credits

View File

@@ -12,7 +12,10 @@ angular.module('admin.orderCycles')
$scope.StatusMessage = StatusMessage
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', 'You have unsaved changes' if newValue
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded

View File

@@ -13,7 +13,10 @@ angular.module('admin.orderCycles')
$scope.StatusMessage = StatusMessage
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', 'You have unsaved changes' if newValue
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded

View File

@@ -8,7 +8,10 @@ angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl"
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', 'You have unsaved changes' if newValue
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.init = (enterprises) ->
enterprise = enterprises[Object.keys(enterprises)[0]]

View File

@@ -10,7 +10,10 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl",
$scope.init()
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', 'You have unsaved changes' if newValue
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded

View File

@@ -11,6 +11,14 @@ angular.module("admin.utils").factory "StatusMessage", ($timeout) ->
text: ""
style: {}
invalidMessage: ""
setValidation: (isValid) ->
if isValid
StatusMessage.invalidMessage = ''
else
StatusMessage.invalidMessage = t("admin.form_invalid")
active: ->
@statusMessage.text != ''

View File

@@ -1,6 +1,9 @@
#save-bar.animate-show{ ng: { show: 'dirty || persist || StatusMessage.active()' } }
.container
.eight.columns.alpha
%h5#status-message{ ng: { style: 'StatusMessage.statusMessage.style' } }
%h5#status-message{ ng: { show: "StatusMessage.invalidMessage == ''", style: 'StatusMessage.statusMessage.style' } }
{{ StatusMessage.statusMessage.text || " " }}
%h5#status-message{ ng: { show: "StatusMessage.invalidMessage !== ''" }, style: 'color: #da5354' }
{{ StatusMessage.invalidMessage || " " }}
.eight.columns.omega.text-right{ ng: { transclude: true } }

View File

@@ -74,6 +74,9 @@ form.order_cycle {
margin-bottom: 0.5em;
}
}
.icon-question-sign {
font-size: 18px;
}
table.exchanges {
tr td.active {
width: 20px;
@@ -113,6 +116,14 @@ form.order_cycle {
margin-right: 2em;
}
}
.collection-details {
input {
width: 90%
}
span {
font-size: 1rem
}
}
}
.coordinator-fees {
margin-top: 1em;

View File

@@ -23,6 +23,11 @@ class BaseController < ApplicationController
private
def set_order_cycles
unless @distributor.ready_for_checkout?
@order_cycles = OrderCycle.where('false')
return
end
@order_cycles = OrderCycle.with_distributor(@distributor).active
.order(@distributor.preferred_shopfront_order_cycle_order)

View File

@@ -54,12 +54,9 @@ module CheckoutHelper
end
def display_adjustment_tax_rates(adjustment)
tax_rate = (adjustment.included_tax / (adjustment.amount - adjustment.included_tax)).round(2)
if tax_rate == 0 || tax_rate.infinite?
""
else
number_to_percentage(tax_rate * 100, :precision => 1)
end
tax_rates = adjustment.tax_rates
return "" if adjustment.amount == adjustment.included_tax
tax_rates.map { |tr| number_to_percentage(tr.amount * 100, :precision => 1) }.join(", ")
end
def display_adjustment_amount(adjustment)

View File

@@ -34,10 +34,30 @@ module Spree
included_tax > 0
end
def display_included_tax
Spree::Money.new(included_tax, { :currency => currency })
def tax_rates
case originator
when Spree::TaxRate
[originator]
when EnterpriseFee
case source
when Spree::LineItem
tax_category = originator.inherits_tax_category? ? source.product.tax_category : originator.tax_category
return tax_category ? tax_category.tax_rates.match(source.order) : []
when Spree::Order
return originator.tax_category ? originator.tax_category.tax_rates.match(source) : []
end
else
[find_closest_tax_rate_from_included_tax]
end
end
def find_closest_tax_rate_from_included_tax
approximation = (included_tax / (amount - included_tax))
return nil if approximation.infinite? or approximation.zero?
Spree::TaxRate.order("ABS(amount - #{approximation})").first
end
def self.without_callbacks
skip_callback :save, :after, :update_adjustable
skip_callback :destroy, :after, :update_adjustable

View File

@@ -234,12 +234,12 @@ Spree::Order.class_eval do
def tax_adjustment_totals
tax_adjustments.each_with_object(Hash.new) do |adjustment, hash|
if adjustment.originator_type == "Spree::TaxRate"
tax_rate = adjustment.originator.amount
else
tax_rate = (adjustment.included_tax / (adjustment.amount - adjustment.included_tax)).round(2)
end
hash.update({tax_rate => adjustment.included_tax}) { |_tax_rate, amount1, amount2| amount1 + amount2 }
tax_rates = adjustment.tax_rates
tax_rates_hash = Hash[tax_rates.collect do |tax_rate|
tax_amount = tax_rates.one? ? adjustment.included_tax : tax_rate.compute_tax(adjustment.amount)
[tax_rate.amount, tax_amount]
end]
hash.update(tax_rates_hash) { |_tax_rate, amount1, amount2| amount1 + amount2 }
end
end

View File

@@ -9,14 +9,16 @@
selected
- if type == 'supplier'
%td.receival-details
= text_field_tag 'order_cycle_incoming_exchange_{{ $index }}_receival_instructions', '', 'id' => 'order_cycle_incoming_exchange_{{ $index }}_receival_instructions', 'placeholder' => 'Receival instructions', 'ng-model' => 'exchange.receival_instructions'
= text_field_tag 'order_cycle_incoming_exchange_{{ $index }}_receival_instructions', '', 'id' => 'order_cycle_incoming_exchange_{{ $index }}_receival_instructions', 'placeholder' => t('.receival_instructions_placeholder'), 'ng-model' => 'exchange.receival_instructions'
- if type == 'distributor'
%td.tags.panel-toggle.text-center{ name: "tags", ng: { if: 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' } }
{{ exchange.tags.length }}
%td.collection-details
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', 'placeholder' => 'Ready for (ie. Date / Time)', 'ng-model' => 'exchange.pickup_time', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator'
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', 'required' => 'required', 'placeholder' => t('.pickup_time_placeholder'), 'ng-model' => 'exchange.pickup_time', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator', 'maxlength' => 35
%span.icon-question-sign{'ofn-with-tip' => t('admin.order_cycles.edit.pickup_time_tip')}
%br/
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', 'placeholder' => 'Pick-up instructions', 'ng-model' => 'exchange.pickup_instructions', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator'
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', 'placeholder' => t('.pickup_instructions_placeholder'), 'ng-model' => 'exchange.pickup_instructions', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator'
%span.icon-question-sign{'ofn-with-tip' => t('admin.order_cycles.edit.pickup_instructions_tip')}
%td.fees
%ol{ ng: { show: 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' } }
%li{'ng-repeat' => 'enterprise_fee in exchange.enterprise_fees'}

View File

@@ -4,11 +4,13 @@
.alpha.two.columns
= label_tag t('.ready_for')
.six.columns
= text_field_tag 'order_cycle_outgoing_exchange_0_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_time', 'placeholder' => t('.ready_for_placeholder'), 'ng-model' => 'outgoing_exchange.pickup_time', 'size' => 30
= text_field_tag 'order_cycle_outgoing_exchange_0_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_time', 'required' => 'required', 'placeholder' => t('.ready_for_placeholder'), 'ng-model' => 'outgoing_exchange.pickup_time', 'size' => 30, 'maxlength' => 35
%span.icon-question-sign{'ofn-with-tip' => t('admin.order_cycles.edit.pickup_time_tip')}
.two.columns
= label_tag t('.customer_instructions')
.six.columns.omega
= text_field_tag 'order_cycle_outgoing_exchange_0_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_instructions', 'placeholder' => t('.customer_instructions_placeholder'), 'ng-model' => 'outgoing_exchange.pickup_instructions', 'size' => 30
%span.icon-question-sign{'ofn-with-tip' => t('admin.order_cycles.edit.pickup_instructions_tip')}
= label_tag t('.products')
%table.exchanges

View File

@@ -28,8 +28,8 @@
= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => ng_controller, name: 'order_cycle_form'} do |f|
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
%input.red{ type: "button", value: t(:update), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty" } }
%input.red{ type: "button", value: t('.update_and_close'), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty" } }
%input.red{ type: "button", value: t(:update), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input.red{ type: "button", value: t('.update_and_close'), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? 'Cancel' : 'Close'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
- if order_cycles_simple_form

View File

@@ -7,7 +7,7 @@
= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => ng_controller, name: 'order_cycle_form'} do |f|
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
%input.red{ type: "button", value: t(:create), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty" } }
%input.red{ type: "button", value: t(:create), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? 'Cancel' : 'Close'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
- if order_cycles_simple_form

View File

@@ -0,0 +1,7 @@
<%= t('.request_sent_text') %>
<%= t('.link_text') %>
<%= @edit_password_reset_url %>
<%= t('.issue_text') %>

View File

@@ -35,6 +35,7 @@ Openfoodnetwork::Application.configure do
# Tests assume English text on the site.
config.i18n.default_locale = "en"
I18n.locale = config.i18n.locale = config.i18n.default_locale
# Use SQL instead of Active Record's schema dumper when creating the test database.
# This is necessary if your schema can't be completely dumped by the schema dumper,

View File

@@ -70,6 +70,8 @@ en-GB:
clear_all: Clear All
start_date: "Start Date"
end_date: "End Date"
unsaved_changes: "You have unsaved changes"
form_invalid: "Form contains missing or invalid fields"
columns: Columns
actions: Actions
viewing: "Viewing: %{current_view_name}"
@@ -198,7 +200,9 @@ en-GB:
variants_without_unit_value: "WARNING: Some variants do not have a unit value"
order_cycles:
edit:
choose_products_from: "Choose Products From:"
choose_products_from: 'Choose Products From:'
pickup_time_tip: When orders from this OC will be ready for the customer
pickup_instructions_tip: These instructions are shown to customers after they complete an order
enterprise:
select_outgoing_oc_products_from: Select outgoing OC products from
enterprises:

View File

@@ -105,6 +105,8 @@ en:
clear_all: Clear All
start_date: "Start Date"
end_date: "End Date"
unsaved_changes: "You have unsaved changes"
form_invalid: "Form contains missing or invalid fields"
columns: Columns
actions: Actions
@@ -275,10 +277,6 @@ en:
order_error: "Some errors must be resolved before you can update orders.\nAny fields with red borders contain errors."
variants_without_unit_value: "WARNING: Some variants do not have a unit value"
order_cycles:
edit:
choose_products_from: "Choose Products From:"
enterprise:
select_outgoing_oc_products_from: Select outgoing OC products from
@@ -467,6 +465,16 @@ en:
next_step: Next step
choose_starting_point: 'Choose your starting point:'
order_cycles:
edit:
advanced_settings: Advanced Settings
update_and_close: Update and Close
choose_products_from: 'Choose Products From:'
pickup_time_tip: When orders from this OC will be ready for the customer
pickup_instructions_tip: These instructions are shown to customers after they complete an order
exchange_form:
pickup_instructions_placeholder: "Pick-up instructions"
pickup_time_placeholder: "Ready for (ie. Date / Time)"
receival_instructions_placeholder: "Receival instructions"
advanced_settings:
title: Advanced Settings
choose_product_tip: You can opt to restrict all available products (both incoming and outgoing), to only those in %{inventory}'s inventory.
@@ -485,7 +493,7 @@ en:
distributor: Distributor
products: Products
tags: Tags
delivery_detaisl: Pickup / Delivery details
delivery_details: Pickup / Delivery details
debug_info: Debug information
name_and_timing_form:
name: Name
@@ -503,9 +511,6 @@ en:
customer_instructions_placeholder: Pick-up or delivery notes
products: Products
fees: Fees
edit:
advanced_settings: Advanced Settings
update_and_close: Update and Close
producer_properties:
index:
title: Producer Properties
@@ -1591,3 +1596,13 @@ Please follow the instructions there to make your enterprise visible on the Open
orders:
invoice:
tax_invoice: "TAX INVOICE: "
user_mailer:
reset_password_instructions:
request_sent_text: |
A request to reset your password has been made.
If you did not make this request, simply ignore this email.
link_text: >
If you did make this request just click the link below:
issue_text: |
If the above URL does not work try copying and pasting it into your browser.
If you continue to have problems please feel free to contact us.

View File

@@ -32,21 +32,11 @@ module OpenFoodNetwork
end
def adjustment_tax(adjustable, adjustment)
tax_rates = rates_for(adjustable)
tax_rates = adjustment.tax_rates
tax_rates.select(&:included_in_price).sum do |rate|
rate.compute_tax adjustment.amount
end
end
def rates_for(adjustable)
case adjustable
when Spree::LineItem
tax_category = enterprise_fee.inherits_tax_category? ? adjustable.product.tax_category : enterprise_fee.tax_category
return tax_category ? tax_category.tax_rates.match(adjustable.order) : []
when Spree::Order
return enterprise_fee.tax_category ? enterprise_fee.tax_category.tax_rates.match(adjustable) : []
end
end
end
end

View File

@@ -1,7 +1,7 @@
module OpenFoodNetwork
class EnterpriseInjectionData
def active_distributors
@active_distributors ||= Enterprise.distributors_with_active_order_cycles
@active_distributors ||= Enterprise.distributors_with_active_order_cycles.ready_for_checkout
end
def earliest_closing_times

View File

@@ -1,14 +1,22 @@
namespace :karma do
task :start => :environment do
task :start => :environment do |task|
continue_only_in_test_env task
with_tmp_config :start
end
task :run => :environment do
task :run => :environment do |task|
continue_only_in_test_env task
with_tmp_config :start, "--single-run"
end
private
def continue_only_in_test_env task
if Rails.env != 'test'
raise "Task must be called in test environment:\n bundle exec rake #{task.name} RAILS_ENV=test"
end
end
def with_tmp_config(command, args = nil)
Tempfile.open('karma_unit.js', Rails.root.join('tmp') ) do |f|
f.write unit_js(application_spec_files << i18n_file)

View File

@@ -14,4 +14,4 @@ echo "--- Bundling"
bundle install
echo "--- Running tests"
bundle exec rake karma:run
./script/karma run

13
script/karma Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/sh
task="$1"
if [ "$task" = "run" ] || [ "$task" = "start" ]; then
exec bundle exec rake "karma:$task" RAILS_ENV=test
else
echo "Usage:"
echo " $0 run # to run the tests once"
echo " $0 start # to run the tests on every file modification"
exit 1
fi

View File

@@ -1,7 +1,9 @@
require 'spec_helper'
describe ShopController do
let(:distributor) { create(:distributor_enterprise) }
let!(:pm) { create(:payment_method) }
let!(:sm) { create(:shipping_method) }
let(:distributor) { create(:distributor_enterprise, payment_methods: [pm], shipping_methods: [sm]) }
it "redirects to the home page if no distributor is selected" do
spree_get :show

View File

@@ -6,7 +6,7 @@ describe ShopsController do
let!(:invisible_distributor) { create(:distributor_enterprise, visible: false) }
before do
Enterprise.stub(:distributors_with_active_order_cycles) { [distributor] }
Enterprise.stub_chain("distributors_with_active_order_cycles.ready_for_checkout") { [distributor] }
end
# Exclusion from actual rendered view handled in features/consumer/home

View File

@@ -350,6 +350,8 @@ feature %q{
fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'New instructions 0'
fill_in 'order_cycle_outgoing_exchange_1_pickup_time', with: 'New time 1'
fill_in 'order_cycle_outgoing_exchange_1_pickup_instructions', with: 'New instructions 1'
fill_in 'order_cycle_outgoing_exchange_2_pickup_time', with: 'New time 2'
fill_in 'order_cycle_outgoing_exchange_2_pickup_instructions', with: 'New instructions 2'
page.find("table.exchanges tr.distributor-#{distributor.id} td.tags").click
within ".exchange-tags" do
@@ -616,6 +618,11 @@ feature %q{
select 'Permitted distributor', from: 'new_distributor_id'
click_button 'Add distributor'
fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'pickup time'
fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions'
fill_in 'order_cycle_outgoing_exchange_1_pickup_time', with: 'pickup time 2'
fill_in 'order_cycle_outgoing_exchange_1_pickup_instructions', with: 'pickup instructions'
# Should only have suppliers / distributors listed which the user is managing or
# has E2E permission to add products to order cycles
page.should_not have_select 'new_supplier_id', with_options: [supplier_unmanaged.name]

View File

@@ -6,8 +6,8 @@ feature 'Shops', js: true do
let!(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let!(:invisible_distributor) { create(:distributor_enterprise, visible: false) }
let(:d1) { create(:distributor_enterprise) }
let(:d2) { create(:distributor_enterprise) }
let!(:d1) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let!(:d2) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) }
let!(:producer) { create(:supplier_enterprise) }
let!(:er) { create(:enterprise_relationship, parent: distributor, child: producer) }
@@ -57,6 +57,20 @@ feature 'Shops', js: true do
end
end
describe "showing available hubs" do
let!(:hub) { create(:distributor_enterprise, with_payment_and_shipping: false) }
let!(:order_cycle) { create(:simple_order_cycle, distributors: [hub], coordinator: hub) }
let!(:producer) { create(:supplier_enterprise) }
let!(:er) { create(:enterprise_relationship, parent: hub, child: producer) }
it "does not show hubs that are not ready for checkout" do
visit shops_path
Enterprise.ready_for_checkout.should_not include hub
page.should_not have_content hub.name
end
end
describe "filtering by product property" do
let!(:order_cycle) { create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) }
let!(:p1) { create(:simple_product, supplier: producer) }
@@ -92,7 +106,7 @@ feature 'Shops', js: true do
describe "taxon badges" do
let!(:closed_oc) { create(:closed_order_cycle, distributors: [shop], variants: [p_closed.variants.first]) }
let!(:p_closed) { create(:simple_product, taxons: [taxon_closed]) }
let(:shop) { create(:distributor_enterprise) }
let(:shop) { create(:distributor_enterprise, with_payment_and_shipping: true) }
let(:taxon_closed) { create(:taxon, name: 'Closed') }
describe "open shops" do

View File

@@ -2,7 +2,7 @@ require 'spec_helper'
describe Spree::UserMailer do
let(:user) { build(:user) }
after do
ActionMailer::Base.deliveries.clear
end
@@ -17,4 +17,37 @@ describe Spree::UserMailer do
Spree::UserMailer.signup_confirmation(user).deliver
ActionMailer::Base.deliveries.count.should == 1
end
# adapted from https://github.com/spree/spree_auth_devise/blob/70737af/spec/mailers/user_mailer_spec.rb
describe '#reset_password_instructions' do
describe 'message contents' do
before do
@message = described_class.reset_password_instructions(user)
end
context 'subject includes' do
it 'translated devise instructions' do
expect(@message.subject).to include "Password Reset Instructions"
end
it 'Spree site name' do
expect(@message.subject).to include Spree::Config[:site_name]
end
end
context 'body includes' do
it 'password reset url' do
expect(@message.body.raw_source).to include root_url + "user/spree_user/password/edit"
end
end
end
describe 'legacy support for User object' do
it 'sends an email' do
expect do
Spree::UserMailer.reset_password_instructions(user).deliver
end.to change(ActionMailer::Base.deliveries, :size).by(1)
end
end
end
end

View File

@@ -1,3 +1,5 @@
require 'spec_helper'
module Spree
describe Adjustment do
it "has metadata" do
@@ -279,6 +281,21 @@ module Spree
adjustment.included_tax.should == 10.00
end
end
describe "getting the corresponding tax rate" do
let!(:adjustment_with_tax) { create(:adjustment, amount: 50, included_tax: 10) }
let!(:adjustment_without_tax) { create(:adjustment, amount: 50, included_tax: 0) }
let!(:tax_rate) { create(:tax_rate, calculator: Spree::Calculator::DefaultTax.new, amount: 0.25) }
let!(:other_tax_rate) { create(:tax_rate, calculator: Spree::Calculator::DefaultTax.new, amount: 0.3) }
it "returns nil if there is no included tax" do
adjustment_without_tax.find_closest_tax_rate_from_included_tax.should == nil
end
it "returns the most accurate tax rate" do
adjustment_with_tax.find_closest_tax_rate_from_included_tax.should == tax_rate
end
end
end
end
end

View File

@@ -276,6 +276,50 @@ describe Spree::Order do
end
end
describe "getting a hash of all taxes" do
let(:zone) { create(:zone_with_member) }
let(:coordinator) { create(:distributor_enterprise, charges_sales_tax: true) }
let(:tax_rate10) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.1, zone: zone) }
let(:tax_rate15) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.15, zone: zone) }
let(:tax_rate20) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.2, zone: zone) }
let(:tax_category10) { create(:tax_category, tax_rates: [tax_rate10]) }
let(:tax_category15) { create(:tax_category, tax_rates: [tax_rate15]) }
let(:tax_category20) { create(:tax_category, tax_rates: [tax_rate20]) }
let(:variant) { create(:variant, product: create(:product, tax_category: tax_category10)) }
let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 46.0)) }
let(:enterprise_fee) { create(:enterprise_fee, enterprise: coordinator, tax_category: tax_category20, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 48.0)) }
let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, coordinator_fees: [enterprise_fee], distributors: [coordinator], variants: [variant]) }
let!(:order) { create(:order, shipping_method: shipping_method, bill_address: create(:address), order_cycle: order_cycle, distributor: coordinator) }
let!(:line_item) { create(:line_item, order: order, variant: variant, price: 44.0) }
before do
Spree::Config.shipment_inc_vat = true
Spree::Config.shipping_tax_rate = tax_rate15.amount
order.create_shipment!
Spree::TaxRate.adjust(order)
order.reload.update_distribution_charge!
end
it "returns a hash with all 3 taxes" do
order.tax_adjustment_totals.size.should == 3
end
it "contains tax on line_item" do
order.tax_adjustment_totals[tax_rate10.amount].should == 4.0
end
it "contains tax on shipping_fee" do
order.tax_adjustment_totals[tax_rate15.amount].should == 6.0
end
it "contains tax on enterprise_fee" do
order.tax_adjustment_totals[tax_rate20.amount].should == 8.0
end
end
describe "setting the distributor" do
it "sets the distributor when no order cycle is set" do
d = create(:distributor_enterprise)