mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-23 05:28:53 +00:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74fd019863 | ||
|
|
1207bb5f8f | ||
|
|
d25eea660e | ||
|
|
fdfb155682 | ||
|
|
66d6627c89 | ||
|
|
c5d38d684b | ||
|
|
c2907b839a | ||
|
|
ee653bb825 | ||
|
|
75616e69e7 | ||
|
|
b4b3e21cf6 | ||
|
|
ce90ec0f5b | ||
|
|
2998432744 | ||
|
|
c5aaecf76a | ||
|
|
2e64f54740 | ||
|
|
c7de67a14f | ||
|
|
545e69835d | ||
|
|
e3a757bd2d | ||
|
|
8223d1ce52 | ||
|
|
167846138f | ||
|
|
243e70427d | ||
|
|
0ae3c8d668 | ||
|
|
c8f46e52d3 | ||
|
|
131a916d99 | ||
|
|
9dd9e08694 | ||
|
|
e7180e956f | ||
|
|
7f312caa25 | ||
|
|
8f0d4d23a7 | ||
|
|
d56b4b4109 | ||
|
|
7a01409f5c | ||
|
|
5c634c269b | ||
|
|
bf22484add | ||
|
|
1696dd2de6 | ||
|
|
63988fff4f | ||
|
|
d56790b71e | ||
|
|
c2f725b20c | ||
|
|
b939d41bf5 | ||
|
|
91c4ba03cd | ||
|
|
3f29cdab3c | ||
|
|
60a4d36408 | ||
|
|
9513c07c2f | ||
|
|
4b5fd2495f | ||
|
|
939ae20081 | ||
|
|
78e9524767 | ||
|
|
3f5b7aaea9 | ||
|
|
00ab4379c9 | ||
|
|
9dec68032c | ||
|
|
e449ae95d5 | ||
|
|
d0af6ddcc1 | ||
|
|
a17d3f34d9 | ||
|
|
6c5d49ae33 | ||
|
|
7d4389de4a | ||
|
|
93c9181c3f | ||
|
|
7473a2f0bd | ||
|
|
af8544a4fa | ||
|
|
be156e5621 | ||
|
|
ec8fcecbd6 | ||
|
|
35ae3a424a | ||
|
|
c2c83898a2 | ||
|
|
2879f77aa1 | ||
|
|
68032657c3 | ||
|
|
be4037d05a | ||
|
|
9661e8a53e | ||
|
|
5e93c27277 | ||
|
|
fcb3b67efb | ||
|
|
0629153362 | ||
|
|
5e871fc71e | ||
|
|
35e03ea3c7 | ||
|
|
ee7ed56f44 | ||
|
|
4140209820 | ||
|
|
1bb4fdf294 | ||
|
|
9ca1a9e33f | ||
|
|
62af416696 | ||
|
|
bcf39acebc | ||
|
|
82186118a7 |
@@ -13,6 +13,9 @@ CAPYBARA_MAX_WAIT_TIME="10"
|
||||
# successful fallback to `en`.
|
||||
LOCALE="en_TST"
|
||||
|
||||
# For multilingual - ENV doesn't have array so pass it as string with commas
|
||||
AVAILABLE_LOCALES="en_TST,es,pt"
|
||||
|
||||
OFN_REDIS_JOBS_URL="redis://localhost:6379/2"
|
||||
|
||||
SECRET_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/release.md
vendored
3
.github/ISSUE_TEMPLATE/release.md
vendored
@@ -32,7 +32,8 @@ assignees: ''
|
||||
- [ ] Stripe with Authentication required card: `4000002760003184` as shopper and as Admin. As admin, check authorization through customer account `/account#/transactions` and email.
|
||||
- [ ] Pay with Paypal.
|
||||
- [ ] Order on mobile.
|
||||
- [ ] Notify a deployer to deploy it.
|
||||
- [ ] Explore a bit the platform to see if there is nothing unusual (15 min. max)
|
||||
- [ ] Comment on the issue: if it's all good, move to ready to go. If there are issues, don't forget to mention your Desktop/Browser version and number and ping @ reviewers so someone available can have a look
|
||||
|
||||
## 3. Deployment at beginning of week
|
||||
|
||||
|
||||
2
.github/workflows/linters.yml
vendored
2
.github/workflows/linters.yml
vendored
@@ -5,7 +5,7 @@ permissions:
|
||||
jobs:
|
||||
lint:
|
||||
name: reviewdog
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04 # same as build.yml so it can share bundler cache
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
||||
3
Gemfile
3
Gemfile
@@ -63,7 +63,6 @@ gem "taler"
|
||||
gem 'devise'
|
||||
gem 'devise-encryptable'
|
||||
gem 'devise-i18n'
|
||||
gem 'devise-token_authenticatable'
|
||||
gem 'jwt', '~> 2.3'
|
||||
gem 'oauth2', '~> 1.4.7' # Used for Stripe Connect
|
||||
|
||||
@@ -113,7 +112,7 @@ gem "turbo-rails"
|
||||
|
||||
gem 'combine_pdf'
|
||||
gem 'wicked_pdf', github: "openfoodfoundation/wicked_pdf", branch: "master"
|
||||
gem 'wkhtmltopdf-binary'
|
||||
gem 'wkhtmltopdf-binary', source: 'https://rubygems.org' # due to https://github.com/gem-coop/gem.coop/issues/36
|
||||
|
||||
gem 'immigrant'
|
||||
gem 'roo' # read spreadsheets
|
||||
|
||||
38
Gemfile.lock
38
Gemfile.lock
@@ -185,7 +185,7 @@ GEM
|
||||
ast (2.4.3)
|
||||
attr_required (1.0.2)
|
||||
aws-eventstream (1.4.0)
|
||||
aws-partitions (1.1223.0)
|
||||
aws-partitions (1.1227.0)
|
||||
aws-sdk-core (3.243.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
@@ -197,15 +197,15 @@ GEM
|
||||
aws-sdk-kms (1.122.0)
|
||||
aws-sdk-core (~> 3, >= 3.241.4)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.213.0)
|
||||
aws-sdk-core (~> 3, >= 3.241.4)
|
||||
aws-sdk-s3 (1.215.0)
|
||||
aws-sdk-core (~> 3, >= 3.243.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.12.1)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
base64 (0.3.0)
|
||||
bcp47_spec (0.2.1)
|
||||
bcrypt (3.1.20)
|
||||
bcrypt (3.1.22)
|
||||
benchmark (0.5.0)
|
||||
bigdecimal (3.3.1)
|
||||
bindata (2.5.1)
|
||||
@@ -279,13 +279,13 @@ GEM
|
||||
datafoodconsortium-connector (1.2.0)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||
date (3.5.1)
|
||||
debug (1.11.0)
|
||||
debug (1.11.1)
|
||||
irb (~> 1.10)
|
||||
reline (>= 0.3.8)
|
||||
devise (4.9.4)
|
||||
devise (5.0.3)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 4.1.0)
|
||||
railties (>= 7.0)
|
||||
responders
|
||||
warden (~> 1.2.3)
|
||||
devise-encryptable (0.2.0)
|
||||
@@ -293,8 +293,6 @@ GEM
|
||||
devise-i18n (1.15.0)
|
||||
devise (>= 4.9.0)
|
||||
rails-i18n
|
||||
devise-token_authenticatable (1.1.0)
|
||||
devise (>= 4.0.0, < 5.0.0)
|
||||
diff-lcs (1.6.2)
|
||||
digest (3.2.1)
|
||||
docile (1.4.1)
|
||||
@@ -443,7 +441,7 @@ GEM
|
||||
thor (>= 0.14, < 2.0)
|
||||
jquery-ui-rails (4.2.1)
|
||||
railties (>= 3.2.16)
|
||||
json (2.18.1)
|
||||
json (2.19.2)
|
||||
json-canonicalization (1.0.0)
|
||||
json-jwt (1.17.0)
|
||||
activesupport (>= 4.2)
|
||||
@@ -469,7 +467,8 @@ GEM
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.10.2)
|
||||
base64
|
||||
knapsack_pro (9.2.2)
|
||||
knapsack_pro (9.2.3)
|
||||
logger
|
||||
rake
|
||||
language_server-protocol (3.17.0.5)
|
||||
launchy (3.0.0)
|
||||
@@ -484,7 +483,7 @@ GEM
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
logger (1.7.0)
|
||||
loofah (2.25.0)
|
||||
loofah (2.25.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
mail (2.9.0)
|
||||
@@ -506,7 +505,7 @@ GEM
|
||||
mini_magick (5.3.1)
|
||||
logger
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.6)
|
||||
mini_portile2 (2.8.9)
|
||||
minitest (6.0.2)
|
||||
drb (~> 2.0)
|
||||
prism (~> 1.5)
|
||||
@@ -531,7 +530,7 @@ GEM
|
||||
net-protocol
|
||||
newrelic_rpm (9.24.0)
|
||||
nio4r (2.7.5)
|
||||
nokogiri (1.19.1)
|
||||
nokogiri (1.19.2)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
nokogiri-html5-inference (0.3.0)
|
||||
@@ -613,7 +612,7 @@ GEM
|
||||
eventmachine_httpserver
|
||||
http_parser.rb (~> 0.8.0)
|
||||
multi_json
|
||||
puma (6.5.0)
|
||||
puma (7.2.0)
|
||||
nio4r (~> 2.0)
|
||||
query_count (1.1.1)
|
||||
activerecord (>= 4.2)
|
||||
@@ -969,12 +968,16 @@ GEM
|
||||
websocket-extensions (0.1.5)
|
||||
whenever (1.1.0)
|
||||
chronic (>= 0.6.3)
|
||||
wkhtmltopdf-binary (0.12.6.10)
|
||||
xml-simple (1.1.8)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.7.5)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
wkhtmltopdf-binary (0.12.6.10)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
@@ -1013,7 +1016,6 @@ DEPENDENCIES
|
||||
devise
|
||||
devise-encryptable
|
||||
devise-i18n
|
||||
devise-token_authenticatable
|
||||
dfc_provider!
|
||||
digest
|
||||
dotenv
|
||||
@@ -1125,7 +1127,7 @@ DEPENDENCIES
|
||||
webmock
|
||||
whenever
|
||||
wicked_pdf!
|
||||
wkhtmltopdf-binary
|
||||
wkhtmltopdf-binary!
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.4.8p72
|
||||
|
||||
@@ -2,15 +2,36 @@
|
||||
|
||||
module PaymentGateways
|
||||
class TalerController < BaseController
|
||||
include OrderStockCheck
|
||||
include OrderCompletion
|
||||
|
||||
class StockError < StandardError
|
||||
end
|
||||
|
||||
# The Taler merchant backend has taken the payment.
|
||||
# Now we just need to confirm that and update our local database
|
||||
# before finalising the order.
|
||||
def confirm
|
||||
payment = Spree::Payment.find(params[:payment_id])
|
||||
|
||||
# Process payment early because it's probably paid already.
|
||||
# We want to capture that before any validations raise errors.
|
||||
unless payment.process!
|
||||
return redirect_to order_failed_route(step: "payment")
|
||||
end
|
||||
|
||||
@order = payment.order
|
||||
process_payment_completion!
|
||||
OrderLocker.lock_order_and_variants(@order) do
|
||||
raise StockError unless sufficient_stock?
|
||||
|
||||
process_payment_completion!
|
||||
end
|
||||
rescue Spree::Core::GatewayError => e
|
||||
flash[:notice] = e.message
|
||||
redirect_to order_failed_route(step: "payment")
|
||||
rescue StockError
|
||||
flash[:notice] = t("checkout.payment_cancelled_due_to_stock")
|
||||
redirect_to main_app.checkout_step_path(step: "details")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -102,7 +102,7 @@ module Spree
|
||||
def sign_in_if_change_own_password
|
||||
return unless spree_current_user == @user && @user.password.present?
|
||||
|
||||
sign_in(@user, event: :authentication, bypass: true)
|
||||
bypass_sign_in(@user)
|
||||
end
|
||||
|
||||
def new_email_unconfirmed?
|
||||
|
||||
@@ -674,8 +674,6 @@ module Spree
|
||||
end
|
||||
|
||||
def process_each_payment
|
||||
raise Core::GatewayError, Spree.t(:no_pending_payments) if pending_payments.empty?
|
||||
|
||||
pending_payments.each do |payment|
|
||||
if payment.amount.zero? && zero_priced_order?
|
||||
payment.update_columns(state: "completed", captured_at: Time.zone.now)
|
||||
|
||||
@@ -5,10 +5,11 @@ module Spree
|
||||
include SetUnusedAddressFields
|
||||
|
||||
self.belongs_to_required_by_default = false
|
||||
self.ignored_columns += [:authentication_token]
|
||||
|
||||
searchable_attributes :email
|
||||
|
||||
devise :database_authenticatable, :token_authenticatable, :registerable, :recoverable,
|
||||
devise :database_authenticatable, :registerable, :recoverable,
|
||||
:rememberable, :trackable, :validatable, :omniauthable,
|
||||
:encryptable, :confirmable,
|
||||
encryptor: 'authlogic_sha512', reconfirmable: true,
|
||||
|
||||
@@ -158,10 +158,10 @@ module Openfoodnetwork
|
||||
# Activate observers that should always be running.
|
||||
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
|
||||
|
||||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||
# The default locale is set in the environment.
|
||||
config.i18n.default_locale = OpenFoodNetwork::I18nConfig.default_locale
|
||||
config.i18n.available_locales = OpenFoodNetwork::I18nConfig.available_locales
|
||||
config.i18n.fallbacks = OpenFoodNetwork::I18nConfig.fallbacks
|
||||
I18n.locale = config.i18n.locale = config.i18n.default_locale
|
||||
|
||||
# Calculate digests for locale files so we can know when they change
|
||||
|
||||
@@ -111,8 +111,6 @@ Rails.application.configure do
|
||||
# Raises error for missing translations.
|
||||
# config.i18n.raise_on_missing_translations = true
|
||||
|
||||
config.i18n.fallbacks = [:en]
|
||||
|
||||
# Annotate rendered view with file names.
|
||||
# config.action_view.annotate_rendered_view_with_filenames = true
|
||||
|
||||
|
||||
@@ -91,10 +91,6 @@ Rails.application.configure do
|
||||
# Use https in email links
|
||||
config.action_mailer.default_url_options = { protocol: 'https' }
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = [:en]
|
||||
|
||||
# Send deprecation notices to registered listeners
|
||||
config.active_support.deprecation = :notify
|
||||
|
||||
|
||||
@@ -60,10 +60,6 @@ Openfoodnetwork::Application.configure do
|
||||
# Enable threaded mode
|
||||
# config.threadsafe!
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation can not be found)
|
||||
config.i18n.fallbacks = [:en]
|
||||
|
||||
# Send deprecation notices to registered listeners
|
||||
config.active_support.deprecation = :notify
|
||||
end
|
||||
|
||||
@@ -89,12 +89,6 @@ Rails.application.configure do
|
||||
# Raises error for missing translations.
|
||||
config.i18n.raise_on_missing_translations = true
|
||||
|
||||
# Tests assume English text on the site.
|
||||
config.i18n.default_locale = "en"
|
||||
config.i18n.available_locales = ['en', 'es', 'pt']
|
||||
config.i18n.fallbacks = [:en]
|
||||
I18n.locale = config.i18n.locale = config.i18n.default_locale
|
||||
|
||||
# Annotate rendered view with file names.
|
||||
# config.action_view.annotate_rendered_view_with_filenames = true
|
||||
|
||||
|
||||
@@ -138,11 +138,6 @@ Devise.setup do |config|
|
||||
config.case_insensitive_keys = [:email]
|
||||
end
|
||||
|
||||
Devise::TokenAuthenticatable.setup do |config|
|
||||
# Defines name of the authentication token params key
|
||||
config.token_authentication_key = :auth_token
|
||||
end
|
||||
|
||||
if ENV["OPENID_APP_ID"].present? && ENV["OPENID_APP_SECRET"].present?
|
||||
Devise.setup do |config|
|
||||
site = if Rails.env.development?
|
||||
|
||||
@@ -946,6 +946,12 @@ cy:
|
||||
clone:
|
||||
success: Llwyddwyd i glonio’r cynnyrch
|
||||
error: Methwyd â chlonio’r cynnyrch
|
||||
tag_rules:
|
||||
rules_per_tag:
|
||||
one: "%{tag}has 1 rule"
|
||||
two: "%{tag}has %{count} rules"
|
||||
many: "%{tag}has %{count} rules"
|
||||
other: "%{tag} has %{count} rules"
|
||||
product_import:
|
||||
title: Mewnforio Cynnyrch
|
||||
file_not_found: Ni ddaethpwyd o hyd i ffeil neu ni ellid ei hagor
|
||||
|
||||
@@ -272,6 +272,10 @@ en_GB:
|
||||
no_default_card: "^No default card available for this customer"
|
||||
shipping_method:
|
||||
not_available_to_shop: "is not available to %{shop}"
|
||||
user_invitation:
|
||||
attributes:
|
||||
email:
|
||||
is_already_manager: is already a manager
|
||||
card_details: "Card details"
|
||||
card_type: "Card type"
|
||||
card_type_is: "Card type is"
|
||||
@@ -421,6 +425,11 @@ en_GB:
|
||||
authorization_required:
|
||||
subject: "A payment requires authorisation from the customer"
|
||||
message: "A payment for order %{order_number} requires additional authorisation from the customer. The customer has been notified via email and the payment will appear as pending until it is authorised."
|
||||
refund_available:
|
||||
subject: "Refund from %{shop}"
|
||||
message: |
|
||||
Your payment of %{amount} to %{shop} is being refunded
|
||||
Accept your refund following the link below.
|
||||
producer_mailer:
|
||||
order_cycle:
|
||||
subject: "Order cycle report for %{producer}"
|
||||
@@ -802,6 +811,7 @@ en_GB:
|
||||
bill_address: "Billing Address"
|
||||
ship_address: "Shipping Address"
|
||||
balance: "Balance"
|
||||
credit: "Available Credit"
|
||||
update_address_success: "Address updated successfully."
|
||||
update_address_error: "Sorry! Please input all of the required fields!"
|
||||
edit_bill_address: "Edit Billing Address"
|
||||
@@ -816,12 +826,16 @@ en_GB:
|
||||
guest_label: "Guest checkout"
|
||||
credit_owed: "Credit Owed"
|
||||
balance_due: "Balance Due"
|
||||
id: Id
|
||||
destroy:
|
||||
has_associated_subscriptions: "Delete failed: This customer has active subscriptions. Cancel them first."
|
||||
customer_account_transaction:
|
||||
index:
|
||||
available_credit: "Available credit: %{available_credit}"
|
||||
transaction_date: Transaction Date
|
||||
description: Description
|
||||
amount: Amount
|
||||
created_by: Created by
|
||||
running_balance: Running balance
|
||||
column_preferences:
|
||||
bulk_update:
|
||||
@@ -1414,10 +1428,12 @@ en_GB:
|
||||
show_hide_payment: 'Show or Hide payment methods at checkout'
|
||||
show_hide_order_cycles: 'Show or Hide order cycles in my shopfront'
|
||||
users:
|
||||
description: The users with permission to manage this enterprise.
|
||||
legend: "Users"
|
||||
email_confirmation_notice_html: "Email confirmation is pending. We've sent a confirmation email to %{email}."
|
||||
resend: Resend
|
||||
contact: "Contact"
|
||||
manager: "Manager"
|
||||
owner: 'Owner'
|
||||
contact_tip: "The manager who will receive enterprise emails for orders and notifications. Must have a confirmed email adress."
|
||||
owner_tip: The primary user responsible for this enterprise.
|
||||
@@ -1428,6 +1444,8 @@ en_GB:
|
||||
invite_manager: "Invite Manager"
|
||||
email_confirmed: "Email confirmed"
|
||||
email_not_confirmed: "Email not confirmed"
|
||||
set_as_contact: "Set %{email} as contact"
|
||||
set_as_owner: "Set %{email} as owner"
|
||||
vouchers:
|
||||
legend: Vouchers
|
||||
voucher_code: Voucher Code
|
||||
@@ -1776,6 +1794,11 @@ en_GB:
|
||||
images: "Images"
|
||||
contact: "Contact"
|
||||
web: "Web Resources"
|
||||
stimulus_pagination:
|
||||
navigation: Pagination
|
||||
page: "Page %{number}"
|
||||
previous: Previous page
|
||||
next: Next page
|
||||
enterprise_issues:
|
||||
create_new: Create New
|
||||
resend_email: Resend Email
|
||||
@@ -2005,7 +2028,10 @@ en_GB:
|
||||
user_invitations:
|
||||
new:
|
||||
back: Back
|
||||
description: "Invite a user to sign up and become a manager of this enterprise."
|
||||
eg_email_address: e.g. email address of a new or existing user
|
||||
email: Email
|
||||
invite_new_user: Invite a new user
|
||||
invite: Invite
|
||||
vouchers:
|
||||
new:
|
||||
@@ -2405,7 +2431,7 @@ en_GB:
|
||||
system_step3_text: "Set up payment methods and add your collection and delivery options."
|
||||
cta_headline: "The sustainable food network of our future."
|
||||
cta_label: "Start shopping"
|
||||
stats_headline: "Join over 18k shoppers and producers in creating a new food system"
|
||||
stats_headline: "Join over 21k shoppers and producers in creating a new food system"
|
||||
stats_producers: "food producers"
|
||||
stats_shops: "food shops"
|
||||
stats_shoppers: "food shoppers"
|
||||
@@ -2439,6 +2465,7 @@ en_GB:
|
||||
order_total: Total order
|
||||
order_payment: "Paying via:"
|
||||
no_payment_required: "No payment required"
|
||||
credit_used: "Credit used: %{amount}"
|
||||
customer_credit: Credit
|
||||
order_billing_address: Billing address
|
||||
order_delivery_on: Delivery on
|
||||
@@ -3423,6 +3450,7 @@ en_GB:
|
||||
no_orders_found: "No Orders Found"
|
||||
order_information: "Order Information"
|
||||
new_payment: "New Payment"
|
||||
credit_customer: Credit customer
|
||||
create_or_update_invoice: "Create or Update Invoice"
|
||||
date_completed: "Date Completed"
|
||||
amount: "Amount"
|
||||
@@ -4020,6 +4048,7 @@ en_GB:
|
||||
items_cannot_be_shipped: "Items cannot be shipped"
|
||||
gateway_config_unavailable: "Gateway config unavailable"
|
||||
gateway_error: "Payment failed"
|
||||
internal_payment_not_voidable: Payment not voidable
|
||||
more: "More"
|
||||
new_adjustment: "New adjustment"
|
||||
new_tax_category: "New Tax Category"
|
||||
@@ -4514,6 +4543,7 @@ en_GB:
|
||||
paypalexpress: "PayPal Express"
|
||||
stripesca: "Stripe SCA "
|
||||
taler: "Taler"
|
||||
customercredit: "Customer Credit"
|
||||
payments:
|
||||
source_forms:
|
||||
stripe:
|
||||
@@ -4521,6 +4551,7 @@ en_GB:
|
||||
submitting_payment: Submitting payment...
|
||||
paypal:
|
||||
no_payment_via_admin_backend: Paypal payments cannot be captured in the Backoffice
|
||||
customer_credit_successful: Customer has been successfully credited!
|
||||
products:
|
||||
image_upload_error: "Please upload the image in JPG, PNG, GIF, SVG or WEBP format."
|
||||
image_not_processable: "Image attachment is not a valid image."
|
||||
@@ -4836,6 +4867,7 @@ en_GB:
|
||||
orders: Orders
|
||||
cards: Credit Cards
|
||||
transactions: Transactions
|
||||
customer_account_transactions: Customer Transactions
|
||||
settings: Account Settings
|
||||
unconfirmed_email: "Pending email confirmation for: %{unconfirmed_email}. Your email address will be updated once the new email is confirmed."
|
||||
orders:
|
||||
@@ -4846,6 +4878,9 @@ en_GB:
|
||||
authorisation_required: Authorisation Required
|
||||
authorise: Authorise
|
||||
customer_account_transactions:
|
||||
title: Customer Transactions
|
||||
credit_available: "Credit available: %{credit}"
|
||||
transaction_date: Transaction Date
|
||||
description: Description
|
||||
amount: Amount
|
||||
running_balance: Running balance
|
||||
@@ -4988,3 +5023,22 @@ en_GB:
|
||||
invisible_captcha:
|
||||
sentence_for_humans: "Please leave empty"
|
||||
timestamp_error_message: "Please try again after 5 seconds."
|
||||
api_customer_credit: "API credit: %{description}"
|
||||
credit_payment_method:
|
||||
name: Customer credit
|
||||
description: Allow customer to pay with credit
|
||||
success: Payment with credit was sucessful
|
||||
void_success: Credit void was sucessful
|
||||
order_payment_description: "Customer credit: Payment for order: %{order_number}"
|
||||
order_void_description: "Customer credit: Refund for order: %{order_number}"
|
||||
errors:
|
||||
customer_not_found: Customer not found
|
||||
missing_payment: Missing payment
|
||||
credit_payment_method_missing: Credit payment method is missing
|
||||
no_credit_available: No credit available
|
||||
not_enough_credit_available: Not enough credit available
|
||||
orders:
|
||||
customer_credit_service:
|
||||
no_credit_owed: No credit owed
|
||||
credit_payment_method_missing: Customer credit payment method is missing, please check configuration
|
||||
refund_sucessful: Refund successful!
|
||||
|
||||
@@ -549,7 +549,7 @@ hu:
|
||||
on_hand: "Készlet"
|
||||
on_demand: "Igény szerint"
|
||||
tax_category: "Adókategória"
|
||||
inherits_properties: "Örökölje a tulajdonságokat?"
|
||||
inherits_properties: "Tulajdonságok öröklése?"
|
||||
import_date: "Importálás dátuma"
|
||||
actions: Műveletek
|
||||
tags: Címkék
|
||||
@@ -562,7 +562,7 @@ hu:
|
||||
on_hand: "Készlet"
|
||||
on_demand: "Igény szerint"
|
||||
tax_category: "Adókategória"
|
||||
inherits_properties: "Örökölje a tulajdonságokat?"
|
||||
inherits_properties: "Tulajdonságok öröklése?"
|
||||
import_date: "Importálás dátuma"
|
||||
actions:
|
||||
edit: Szerkesztés
|
||||
@@ -798,7 +798,7 @@ hu:
|
||||
display_as: Megjelenítés mint
|
||||
category: Kategória
|
||||
tax_category: Adókategória
|
||||
inherits_properties?: Örökölje a tulajdonságokat?
|
||||
inherits_properties?: Tulajdonságok öröklése?
|
||||
av_on: "Av. On"
|
||||
import_date: Importált
|
||||
upload_an_image: Tölts fel egy képet
|
||||
@@ -1877,7 +1877,9 @@ hu:
|
||||
user_invitations:
|
||||
new:
|
||||
back: Vissza
|
||||
description: "Hívj meg egy felhasználót, hogy regisztráljon és a vállalkozás menedzsere legyen."
|
||||
email: Email
|
||||
invite_new_user: Új felhasználó meghívása
|
||||
invite: Meghívás
|
||||
vouchers:
|
||||
new:
|
||||
@@ -4371,7 +4373,7 @@ hu:
|
||||
display_as: Megjelenítés mint
|
||||
category: Kategória
|
||||
tax_category: Adókategória
|
||||
inherits_properties?: Örökölje a tulajdonságokat?
|
||||
inherits_properties?: Tulajdonságok öröklése?
|
||||
av_on: "Av. On"
|
||||
import_date: "Importálás dátuma"
|
||||
products_variant:
|
||||
|
||||
@@ -95,8 +95,5 @@ Openfoodnetwork::Application.routes.draw do
|
||||
|
||||
resources :customer_account_transaction, only: [:create]
|
||||
end
|
||||
|
||||
match '*path', to: redirect(path: "/api/v0/%{path}"), via: :all,
|
||||
constraints: { path: /(?!v[0-9]).+/ }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,6 +20,10 @@ module OpenFoodNetwork
|
||||
(selectable_locales + [default_locale, source_locale]).uniq
|
||||
end
|
||||
|
||||
def self.fallbacks
|
||||
[default_locale, source_locale].uniq
|
||||
end
|
||||
|
||||
# The default locale that is used when the user doesn't have a preference.
|
||||
def self.default_locale
|
||||
ENV["LOCALE"] || ENV["I18N_LOCALE"] || source_locale
|
||||
|
||||
@@ -6,8 +6,6 @@ module Spree
|
||||
class Money
|
||||
attr_reader :money
|
||||
|
||||
delegate :cents, to: :money
|
||||
|
||||
def initialize(amount, options = {})
|
||||
@money = ::Monetize.parse([amount, options[:currency] || CurrentConfig.get(:currency)].join)
|
||||
|
||||
@@ -32,10 +30,6 @@ module Spree
|
||||
.html_safe # rubocop:disable Rails/OutputSafety
|
||||
end
|
||||
|
||||
def format(options = {})
|
||||
@money.format(@options.merge!(options))
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
@money == other.money
|
||||
end
|
||||
|
||||
@@ -15,7 +15,7 @@ RSpec.describe I18nHelper do
|
||||
|
||||
it "sets the default locale" do
|
||||
helper.set_locale
|
||||
expect(I18n.locale).to eq :en
|
||||
expect(I18n.locale).to eq :en_TST
|
||||
end
|
||||
|
||||
it "sets the chosen locale" do
|
||||
@@ -36,11 +36,11 @@ RSpec.describe I18nHelper do
|
||||
it "ignores unavailable locales" do
|
||||
allow(helper).to receive(:params) { { locale: "xx" } }
|
||||
helper.set_locale
|
||||
expect(I18n.locale).to eq :en
|
||||
expect(I18n.locale).to eq :en_TST
|
||||
end
|
||||
|
||||
it "remembers the last chosen locale" do
|
||||
allow(helper).to receive(:params) { { locale: "en" } }
|
||||
allow(helper).to receive(:params) { { locale: "en_TST" } }
|
||||
helper.set_locale
|
||||
|
||||
allow(helper).to receive(:params) { { locale: "es" } }
|
||||
@@ -71,7 +71,7 @@ RSpec.describe I18nHelper do
|
||||
|
||||
allow(helper).to receive(:params) { {} }
|
||||
helper.set_locale
|
||||
expect(I18n.locale).to eq :en
|
||||
expect(I18n.locale).to eq :en_TST
|
||||
end
|
||||
end
|
||||
|
||||
@@ -82,7 +82,7 @@ RSpec.describe I18nHelper do
|
||||
|
||||
it "sets the default locale" do
|
||||
helper.set_locale
|
||||
expect(I18n.locale).to eq :en
|
||||
expect(I18n.locale).to eq :en_TST
|
||||
end
|
||||
|
||||
it "sets the chosen locale" do
|
||||
@@ -102,7 +102,7 @@ RSpec.describe I18nHelper do
|
||||
end
|
||||
|
||||
it "remembers the last chosen locale" do
|
||||
allow(helper).to receive(:params) { { locale: "en" } }
|
||||
allow(helper).to receive(:params) { { locale: "en_TST" } }
|
||||
helper.set_locale
|
||||
|
||||
allow(helper).to receive(:params) { { locale: "es" } }
|
||||
|
||||
@@ -17,7 +17,7 @@ RSpec.describe Spree::Money do
|
||||
|
||||
it "can get cents" do
|
||||
money = Spree::Money.new(10)
|
||||
expect(money.cents).to eq(1000)
|
||||
expect(money.money.cents).to eq(1000)
|
||||
end
|
||||
|
||||
context "with currency" do
|
||||
|
||||
@@ -282,11 +282,6 @@ RSpec.describe Spree::Order do
|
||||
let(:payment) { build(:payment) }
|
||||
before { allow(order).to receive_messages pending_payments: [payment], total: 10 }
|
||||
|
||||
it "returns false if no pending_payments available" do
|
||||
allow(order).to receive_messages pending_payments: []
|
||||
expect(order.process_payments!).to be_falsy
|
||||
end
|
||||
|
||||
context "when the processing is sucessful" do
|
||||
it "processes the payments" do
|
||||
expect(payment).to receive(:process!)
|
||||
|
||||
@@ -6,17 +6,6 @@ RSpec.describe 'Orders Cycles endpoint' do
|
||||
let(:distributor) { create(:distributor_enterprise) }
|
||||
let(:order_cycle) { create(:order_cycle, distributors: [distributor]) }
|
||||
|
||||
context "requesting the latest version" do
|
||||
let(:path) { "/api/order_cycles/#{order_cycle.id}/products?distributor=#{distributor.id}" }
|
||||
|
||||
it "redirects to v0, preserving URL params" do
|
||||
get path
|
||||
expect(response).to redirect_to(
|
||||
"/api/v0/order_cycles/#{order_cycle.id}/products?distributor=#{distributor.id}"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context "requesting a specific API version" do
|
||||
let(:path) { "/api/v0/order_cycles/#{order_cycle.id}/products?distributor=#{distributor.id}" }
|
||||
|
||||
|
||||
@@ -3,16 +3,19 @@
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe "/payment_gateways/taler/:id" do
|
||||
it "completes the order", :vcr do
|
||||
shop = create(:distributor_enterprise)
|
||||
taler = Spree::PaymentMethod::Taler.create!(
|
||||
let(:shop) { create(:distributor_enterprise) }
|
||||
let(:taler) {
|
||||
Spree::PaymentMethod::Taler.create!(
|
||||
name: "Taler",
|
||||
environment: "test",
|
||||
distributors: [shop],
|
||||
preferred_backend_url: "https://backend.demo.taler.net/instances/sandbox",
|
||||
preferred_api_key: "sandbox",
|
||||
)
|
||||
order = create(:order_ready_for_confirmation, payment_method: taler)
|
||||
}
|
||||
let!(:order) { create(:order_ready_for_confirmation, payment_method: taler) }
|
||||
|
||||
it "completes the order", :vcr do
|
||||
payment = Spree::Payment.last
|
||||
payment.update!(
|
||||
source: taler,
|
||||
@@ -30,4 +33,65 @@ RSpec.describe "/payment_gateways/taler/:id" do
|
||||
payment.reload
|
||||
expect(payment.state).to eq "completed"
|
||||
end
|
||||
|
||||
it "redirects when payment invalid" do
|
||||
payment = Spree::Payment.last
|
||||
payment.update!(
|
||||
source: taler,
|
||||
payment_method: taler,
|
||||
state: "processing", # invalid state to start processing again
|
||||
)
|
||||
|
||||
get payment_gateways_confirm_taler_path(payment_id: payment.id)
|
||||
expect(response).to redirect_to "/checkout/payment"
|
||||
|
||||
payment.reload
|
||||
expect(payment.state).to eq "processing"
|
||||
|
||||
order.reload
|
||||
expect(order.state).to eq "confirmation"
|
||||
end
|
||||
|
||||
it "redirects when payment failed" do
|
||||
payment = Spree::Payment.last
|
||||
payment.update!(
|
||||
source: taler,
|
||||
payment_method: taler,
|
||||
response_code: "2026.020-03R3ETNZZ0DVA",
|
||||
)
|
||||
|
||||
allow_any_instance_of(Taler::Order)
|
||||
.to receive(:fetch).with("order_status").and_return("claimed")
|
||||
|
||||
get payment_gateways_confirm_taler_path(payment_id: payment.id)
|
||||
expect(response).to redirect_to "/checkout/payment"
|
||||
|
||||
payment.reload
|
||||
expect(payment.state).to eq "failed"
|
||||
|
||||
order.reload
|
||||
expect(order.state).to eq "confirmation"
|
||||
end
|
||||
|
||||
it "handles all variants going out of stock" do
|
||||
payment = Spree::Payment.last
|
||||
payment.update!(
|
||||
source: taler,
|
||||
payment_method: taler,
|
||||
response_code: "2026.020-03R3ETNZZ0DVA",
|
||||
)
|
||||
|
||||
allow_any_instance_of(Taler::Order)
|
||||
.to receive(:fetch).with("order_status").and_return("paid")
|
||||
order.line_items[0].variant.on_hand = 0
|
||||
|
||||
get payment_gateways_confirm_taler_path(payment_id: payment.id)
|
||||
expect(response).to redirect_to "/checkout/details"
|
||||
|
||||
payment.reload
|
||||
expect(payment.state).to eq "completed"
|
||||
|
||||
order.reload
|
||||
expect(order.state).to eq "confirmation"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -152,7 +152,7 @@ RSpec.configure do |config|
|
||||
|
||||
# Reset locale for all specs.
|
||||
config.around(:each) do |example|
|
||||
locale = ENV.fetch('LOCALE', 'en_TST')
|
||||
locale = OpenFoodNetwork::I18nConfig.default_locale
|
||||
I18n.with_locale(locale) { example.run }
|
||||
end
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ module StripeStubs
|
||||
|
||||
def stub_capture_request(order, response_mock)
|
||||
stub_request(:post, "https://api.stripe.com/v1/payment_intents/pi_123/capture")
|
||||
.with(body: { amount_to_capture: Spree::Money.new(order.total).cents },
|
||||
.with(body: { amount_to_capture: Spree::Money.new(order.total).money.cents },
|
||||
headers: { 'Stripe-Account' => 'abc123' })
|
||||
.to_return(response_mock)
|
||||
end
|
||||
|
||||
@@ -27,10 +27,6 @@ module WebHelper
|
||||
yield
|
||||
end
|
||||
|
||||
def set_i18n_locale(locale = 'en')
|
||||
page.execute_script("I18n.locale = '#{locale}'")
|
||||
end
|
||||
|
||||
def pick_i18n_locale
|
||||
page.evaluate_script("I18n.locale;")
|
||||
end
|
||||
|
||||
@@ -664,16 +664,16 @@ RSpec.describe '
|
||||
end
|
||||
|
||||
it "finally, can invite unregistered users" do
|
||||
within ".reveal-modal" do
|
||||
tomselect_fill_in "user_invitation[email]", with: "email@email.com"
|
||||
expect do
|
||||
within ".reveal-modal" do
|
||||
tomselect_fill_in "user_invitation[email]", with: "email@email.com"
|
||||
|
||||
expect do
|
||||
click_button "Invite"
|
||||
end.to enqueue_job(ActionMailer::MailDeliveryJob).exactly(:twice)
|
||||
end
|
||||
end
|
||||
|
||||
expect(page)
|
||||
.to have_content "email@email.com has been invited to manage this enterprise"
|
||||
expect(page)
|
||||
.to have_content "email@email.com has been invited to manage this enterprise"
|
||||
end.to enqueue_job(ActionMailer::MailDeliveryJob).exactly(:twice)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,17 +10,12 @@ RSpec.describe 'Multilingual' do
|
||||
|
||||
before do
|
||||
login_as admin_user
|
||||
visit spree.admin_dashboard_path
|
||||
end
|
||||
|
||||
it 'has three locales available' do
|
||||
expect(Rails.application.config.i18n[:default_locale]).to eq 'en'
|
||||
expect(Rails.application.config.i18n[:locale]).to eq 'en'
|
||||
expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es', 'pt']
|
||||
end
|
||||
|
||||
it 'can switch language by params' do
|
||||
expect(pick_i18n_locale).to eq 'en'
|
||||
visit spree.admin_dashboard_path
|
||||
|
||||
expect(pick_i18n_locale).to eq 'en_TST'
|
||||
expect(get_i18n_translation('spree_admin_overview_enterprises_header')).to eq 'My Enterprises'
|
||||
expect(page).to have_content 'My Enterprises'
|
||||
expect(admin_user.locale).to be_nil
|
||||
@@ -36,9 +31,9 @@ RSpec.describe 'Multilingual' do
|
||||
|
||||
it 'fallbacks to default_locale' do
|
||||
visit spree.admin_dashboard_path(locale: 'it')
|
||||
expect(pick_i18n_locale).to eq 'en'
|
||||
expect(pick_i18n_locale).to eq 'en_TST'
|
||||
expect(get_i18n_translation('spree_admin_overview_enterprises_header')).to eq 'My Enterprises'
|
||||
expect(page).to have_content 'My Enterprises'
|
||||
expect(admin_user.locale).to be_nil
|
||||
expect(admin_user.reload.locale).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,201 +5,192 @@ require "system_helper"
|
||||
RSpec.describe "Managing users" do
|
||||
include AuthenticationHelper
|
||||
|
||||
context "as super-admin" do
|
||||
before do
|
||||
login_as_admin
|
||||
end
|
||||
let(:admin_user) { create(:admin_user) }
|
||||
|
||||
context "from the index page" do
|
||||
before do
|
||||
create(:user, email: "a@example.com")
|
||||
create(:user, email: "b@example.com")
|
||||
before do
|
||||
login_as admin_user
|
||||
end
|
||||
|
||||
context "from the index page" do
|
||||
let!(:user_a) { create(:user, email: "a@example.com") }
|
||||
let!(:user_b) { create(:user, email: "b@example.com") }
|
||||
|
||||
context "searching users" do
|
||||
it "should display the correct results for a user search" do
|
||||
visit spree.admin_dashboard_path
|
||||
click_link "Users"
|
||||
end
|
||||
|
||||
context "users index page with sorting" do
|
||||
before(:each) do
|
||||
click_link "users_email_title"
|
||||
end
|
||||
|
||||
it "should list users with order email asc" do
|
||||
expect(page).to have_css('table#listing_users')
|
||||
within("table#listing_users") do
|
||||
expect(page).to have_content("a@example.com")
|
||||
expect(page).to have_content("b@example.com")
|
||||
end
|
||||
end
|
||||
|
||||
it "should list users with order email desc" do
|
||||
click_link "users_email_title"
|
||||
within("table#listing_users") do
|
||||
expect(page).to have_content("a@example.com")
|
||||
expect(page).to have_content("b@example.com")
|
||||
end
|
||||
fill_in "q_email_cont", with: "a@example"
|
||||
click_button "Search"
|
||||
within("table#listing_users") do
|
||||
expect(page).to have_content("a@example")
|
||||
expect(page).not_to have_content("b@example")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "searching users" do
|
||||
it "should display the correct results for a user search" do
|
||||
fill_in "q_email_cont", with: "a@example"
|
||||
click_button "Search"
|
||||
within("table#listing_users") do
|
||||
expect(page).to have_content("a@example")
|
||||
expect(page).not_to have_content("b@example")
|
||||
end
|
||||
end
|
||||
context "editing users" do
|
||||
it "should allow editing the user password" do
|
||||
visit spree.admin_users_path
|
||||
click_link("a@example.com")
|
||||
fill_in "user_password", with: "welcome"
|
||||
fill_in "user_password_confirmation", with: "welcome"
|
||||
click_button "Update"
|
||||
|
||||
expect(page).to have_content("Account updated")
|
||||
expect(current_path).to eq spree.edit_admin_user_path(user_a)
|
||||
end
|
||||
|
||||
context "editing users" do
|
||||
before(:each) do
|
||||
click_link("a@example.com")
|
||||
end
|
||||
it "allows to change your own password without logging you out" do
|
||||
visit spree.edit_admin_user_path(admin_user)
|
||||
|
||||
it "should allow editing the user password" do
|
||||
fill_in "user_password", with: "welcome"
|
||||
fill_in "user_password_confirmation", with: "welcome"
|
||||
click_button "Update"
|
||||
fill_in "user_password", with: "welcome"
|
||||
fill_in "user_password_confirmation", with: "welcome"
|
||||
click_button "Update"
|
||||
|
||||
expect(page).to have_content("Account updated")
|
||||
end
|
||||
expect(page).to have_content("Account updated")
|
||||
expect(current_path).to eq spree.edit_admin_user_path(admin_user)
|
||||
end
|
||||
|
||||
it "should let me edit the user email" do
|
||||
fill_in "Email", with: "newemail@example.org"
|
||||
click_button "Update"
|
||||
it "should let me edit the user email" do
|
||||
visit spree.edit_admin_user_path(user_a)
|
||||
|
||||
expect(page).to have_content("The account will be updated once " \
|
||||
"the new email is confirmed.")
|
||||
end
|
||||
fill_in "Email", with: "newemail@example.org"
|
||||
click_button "Update"
|
||||
|
||||
it "should allow to generate, regenarate and clear the user api key" do
|
||||
user = Spree::User.find_by(email: "a@example.com")
|
||||
expect(page).to have_content "NO KEY"
|
||||
expect(page).to have_content("The account will be updated once " \
|
||||
"the new email is confirmed.")
|
||||
end
|
||||
|
||||
click_button "Generate API key"
|
||||
first_user_api_key = user.reload.spree_api_key
|
||||
expect(page).to have_content first_user_api_key
|
||||
it "should allow to generate, regenarate and clear the user api key" do
|
||||
visit spree.edit_admin_user_path(user_a)
|
||||
|
||||
click_button "Regenerate Key"
|
||||
second_user_api_key = user.reload.spree_api_key
|
||||
expect(page).to have_content second_user_api_key
|
||||
expect(second_user_api_key).not_to eq first_user_api_key
|
||||
expect(page).to have_content "NO KEY"
|
||||
|
||||
click_button "Clear key"
|
||||
expect(page).to have_content "NO KEY"
|
||||
end
|
||||
click_button "Generate API key"
|
||||
first_user_api_key = user_a.reload.spree_api_key
|
||||
expect(page).to have_content first_user_api_key
|
||||
|
||||
it "should allow to disable the user and to enable it" do
|
||||
expect(page).to have_unchecked_field "Disabled"
|
||||
check "Disabled"
|
||||
click_button "Update"
|
||||
click_button "Regenerate Key"
|
||||
second_user_api_key = user_a.reload.spree_api_key
|
||||
expect(page).to have_content second_user_api_key
|
||||
expect(second_user_api_key).not_to eq first_user_api_key
|
||||
|
||||
expect(page).to have_content("Account updated")
|
||||
expect(page).to have_checked_field "Disabled"
|
||||
uncheck "Disabled"
|
||||
click_button "Update"
|
||||
click_button "Clear key"
|
||||
expect(page).to have_content "NO KEY"
|
||||
end
|
||||
|
||||
expect(page).to have_content("Account updated")
|
||||
expect(page).to have_unchecked_field "Disabled"
|
||||
end
|
||||
it "should allow to disable the user and to enable it" do
|
||||
visit spree.edit_admin_user_path(user_a)
|
||||
|
||||
it "should toggle the api key generation view" do
|
||||
user = Spree::User.find_by(email: "a@example.com")
|
||||
expect(page).to have_unchecked_field "Disabled"
|
||||
check "Disabled"
|
||||
click_button "Update"
|
||||
|
||||
expect(page).to have_content "NO KEY"
|
||||
expect {
|
||||
click_button("Generate API key")
|
||||
expect(page).to have_content("Key generated")
|
||||
}.to change { user.reload.spree_api_key }.from(nil)
|
||||
expect(page).to have_content("Account updated")
|
||||
expect(page).to have_checked_field "Disabled"
|
||||
uncheck "Disabled"
|
||||
click_button "Update"
|
||||
|
||||
expect(page).to have_content("Account updated")
|
||||
expect(page).to have_unchecked_field "Disabled"
|
||||
end
|
||||
|
||||
it "should toggle the api key generation view" do
|
||||
visit spree.edit_admin_user_path(user_a)
|
||||
|
||||
expect(page).to have_content "NO KEY"
|
||||
expect {
|
||||
click_button("Generate API key")
|
||||
expect(page).to have_content("Key generated")
|
||||
}.to change { user_a.reload.spree_api_key }.from(nil)
|
||||
|
||||
expect(page).to have_unchecked_field "Show API key view for user"
|
||||
|
||||
expect {
|
||||
check "Show API key view for user"
|
||||
expect(page).to have_content("Show API key view has been changed!")
|
||||
expect(page).to have_checked_field "Show API key view for user"
|
||||
}.to change { user_a.reload.show_api_key_view }.from(false).to(true)
|
||||
|
||||
expect {
|
||||
uncheck "Show API key view for user"
|
||||
expect(page).to have_content("Show API key view has been changed!")
|
||||
expect(page).to have_unchecked_field "Show API key view for user"
|
||||
|
||||
expect {
|
||||
check "Show API key view for user"
|
||||
expect(page).to have_content("Show API key view has been changed!")
|
||||
expect(page).to have_checked_field "Show API key view for user"
|
||||
}.to change { user.reload.show_api_key_view }.from(false).to(true)
|
||||
|
||||
expect {
|
||||
uncheck "Show API key view for user"
|
||||
expect(page).to have_content("Show API key view has been changed!")
|
||||
expect(page).to have_unchecked_field "Show API key view for user"
|
||||
}.to change { user.reload.show_api_key_view }.to(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "pagination" do
|
||||
before do
|
||||
# creates 8 more users
|
||||
8.times { create(:user) }
|
||||
expect(Spree::User.count).to eq 11
|
||||
visit spree.admin_users_path
|
||||
end
|
||||
it "displays pagination" do
|
||||
# table displays 10 entries
|
||||
within('tbody') do
|
||||
expect(page).to have_css('tr', count: 10)
|
||||
end
|
||||
within ".pagination" do
|
||||
expect(page).not_to have_content "Previous"
|
||||
expect(page).to have_content "Next"
|
||||
click_on "2"
|
||||
end
|
||||
# table displays 1 entry
|
||||
within('tbody') do
|
||||
expect(page).to have_css('tr', count: 1)
|
||||
end
|
||||
within ".pagination" do
|
||||
expect(page).to have_content "Previous"
|
||||
expect(page).not_to have_content "Next"
|
||||
end
|
||||
end
|
||||
}.to change { user_a.reload.show_api_key_view }.to(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe "creating a user" do
|
||||
it "confirms successful creation" do
|
||||
visit spree.new_admin_user_path
|
||||
|
||||
# shows no confirmation message to start with
|
||||
expect(page).not_to have_text "Email confirmation is pending"
|
||||
|
||||
fill_in "Email", with: "user1@example.org"
|
||||
fill_in "Password", with: "user1Secret"
|
||||
fill_in "Confirm Password", with: "user1Secret"
|
||||
|
||||
expect(page).to have_select "Language", selected: "English"
|
||||
select "Español", from: "Language"
|
||||
|
||||
perform_enqueued_jobs do
|
||||
expect do
|
||||
click_button "Create"
|
||||
end.to change { Spree::User.count }.by 1
|
||||
expect(page).to have_text "Created Successfully"
|
||||
expect(page).to have_text "Email confirmation is pending"
|
||||
|
||||
expect(Spree::User.last.locale).to eq "es"
|
||||
|
||||
expect(ActionMailer::Base.deliveries.first.subject).to match(
|
||||
"Por favor, confirma tu cuenta de OFN"
|
||||
)
|
||||
end
|
||||
context "pagination" do
|
||||
before do
|
||||
# creates 8 more users
|
||||
8.times { create(:user) }
|
||||
expect(Spree::User.count).to eq 11
|
||||
visit spree.admin_users_path
|
||||
end
|
||||
end
|
||||
|
||||
describe "resending confirmation email" do
|
||||
let(:user) { create :user, confirmed_at: nil }
|
||||
|
||||
it "displays success" do
|
||||
visit spree.edit_admin_user_path user
|
||||
|
||||
expect do
|
||||
# The `a` element doesn't have an href, so we can't use click_link.
|
||||
find("a", text: "Resend").click
|
||||
expect(page).to have_text "Resend done"
|
||||
end.to enqueue_job ActionMailer::MailDeliveryJob
|
||||
it "displays pagination" do
|
||||
# table displays 10 entries
|
||||
within('tbody') do
|
||||
expect(page).to have_css('tr', count: 10)
|
||||
end
|
||||
within ".pagination" do
|
||||
expect(page).not_to have_content "Previous"
|
||||
expect(page).to have_content "Next"
|
||||
click_on "2"
|
||||
end
|
||||
# table displays 1 entry
|
||||
within('tbody') do
|
||||
expect(page).to have_css('tr', count: 1)
|
||||
end
|
||||
within ".pagination" do
|
||||
expect(page).to have_content "Previous"
|
||||
expect(page).not_to have_content "Next"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "creating a user" do
|
||||
it "confirms successful creation" do
|
||||
visit spree.new_admin_user_path
|
||||
|
||||
# shows no confirmation message to start with
|
||||
expect(page).not_to have_text "Email confirmation is pending"
|
||||
|
||||
fill_in "Email", with: "user1@example.org"
|
||||
fill_in "Password", with: "user1Secret"
|
||||
fill_in "Confirm Password", with: "user1Secret"
|
||||
|
||||
expect(page).to have_select "Language", selected: "English"
|
||||
select "Español", from: "Language"
|
||||
|
||||
perform_enqueued_jobs do
|
||||
expect do
|
||||
click_button "Create"
|
||||
end.to change { Spree::User.count }.by 1
|
||||
expect(page).to have_text "Created Successfully"
|
||||
expect(page).to have_text "Email confirmation is pending"
|
||||
|
||||
expect(Spree::User.last.locale).to eq "es"
|
||||
|
||||
expect(ActionMailer::Base.deliveries.first.subject).to match(
|
||||
"Por favor, confirma tu cuenta de OFN"
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "resending confirmation email" do
|
||||
let(:user) { create :user, confirmed_at: nil }
|
||||
|
||||
it "displays success" do
|
||||
visit spree.edit_admin_user_path user
|
||||
|
||||
expect do
|
||||
# The `a` element doesn't have an href, so we can't use click_link.
|
||||
find("a", text: "Resend").click
|
||||
expect(page).to have_text "Resend done"
|
||||
end.to enqueue_job ActionMailer::MailDeliveryJob
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -273,7 +273,7 @@ RSpec.describe "Authentication" do
|
||||
expect_logged_in
|
||||
|
||||
expect(page).to have_content 'SHOP NOW'
|
||||
expect(user.reload.locale).to eq "en"
|
||||
expect(user.reload.locale).to eq "en_TST"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ RSpec.describe "As a consumer, I want to checkout my order" do
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
visit checkout_path
|
||||
end
|
||||
|
||||
context "payment step" do
|
||||
@@ -67,6 +66,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do
|
||||
|
||||
context "with a transaction fee" do
|
||||
before do
|
||||
visit checkout_path
|
||||
click_button "Next - Order summary"
|
||||
end
|
||||
|
||||
@@ -84,6 +84,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do
|
||||
|
||||
context "after completing the order" do
|
||||
before do
|
||||
visit checkout_path
|
||||
click_on "Complete order"
|
||||
end
|
||||
it_behaves_like "displays the transaction fee", "order confirmation"
|
||||
@@ -277,7 +278,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do
|
||||
|
||||
describe "choosing" do
|
||||
shared_examples "different payment methods" do |pay_method|
|
||||
context "checking out with #{pay_method}", if: pay_method.eql?("Stripe SCA") == false do
|
||||
context "checking out with #{pay_method}" do
|
||||
before do
|
||||
visit checkout_step_path(:payment)
|
||||
end
|
||||
@@ -291,46 +292,9 @@ RSpec.describe "As a consumer, I want to checkout my order" do
|
||||
expect(order.reload.state).to eq "complete"
|
||||
end
|
||||
end
|
||||
|
||||
context "for Stripe SCA", if: pay_method.eql?("Stripe SCA") do
|
||||
around do |example|
|
||||
with_stripe_setup { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stripe_enable
|
||||
visit checkout_step_path(:payment)
|
||||
end
|
||||
|
||||
it "selects Stripe SCA and proceeds to the summary step" do
|
||||
choose pay_method.to_s
|
||||
fill_out_card_details
|
||||
click_on "Next - Order summary"
|
||||
proceed_to_summary
|
||||
end
|
||||
|
||||
context "when saving card" do
|
||||
it "selects Stripe SCA and proceeds to the summary step" do
|
||||
stub_customers_post_request(email: order.user.email)
|
||||
stub_payment_method_attach_request
|
||||
|
||||
choose pay_method.to_s
|
||||
fill_out_card_details
|
||||
check "Save card for future use"
|
||||
|
||||
click_on "Next - Order summary"
|
||||
proceed_to_summary
|
||||
|
||||
# Verify card has been saved with correct stripe IDs
|
||||
user_credit_card = order.reload.user.credit_cards.first
|
||||
expect(user_credit_card.gateway_payment_profile_id).to eq "pm_123"
|
||||
expect(user_credit_card.gateway_customer_profile_id).to eq "cus_A123"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "shared examples" do
|
||||
describe "payment method" do
|
||||
let!(:cash) { create(:payment_method, distributors: [distributor], name: "Cash") }
|
||||
|
||||
context "Cash" do
|
||||
@@ -365,7 +329,40 @@ RSpec.describe "As a consumer, I want to checkout my order" do
|
||||
create(:stripe_sca_payment_method, distributors: [distributor], name: "Stripe SCA")
|
||||
}
|
||||
|
||||
it_behaves_like "different payment methods", "Stripe SCA"
|
||||
around do |example|
|
||||
with_stripe_setup { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stripe_enable
|
||||
visit checkout_step_path(:payment)
|
||||
end
|
||||
|
||||
it "selects Stripe SCA and proceeds to the summary step" do
|
||||
choose "Stripe SCA"
|
||||
fill_out_card_details
|
||||
click_on "Next - Order summary"
|
||||
proceed_to_summary
|
||||
end
|
||||
|
||||
context "when saving card" do
|
||||
it "selects Stripe SCA and proceeds to the summary step" do
|
||||
stub_customers_post_request(email: order.user.email)
|
||||
stub_payment_method_attach_request
|
||||
|
||||
choose "Stripe SCA"
|
||||
fill_out_card_details
|
||||
check "Save card for future use"
|
||||
|
||||
click_on "Next - Order summary"
|
||||
proceed_to_summary
|
||||
|
||||
# Verify card has been saved with correct stripe IDs
|
||||
user_credit_card = order.reload.user.credit_cards.first
|
||||
expect(user_credit_card.gateway_payment_profile_id).to eq "pm_123"
|
||||
expect(user_credit_card.gateway_customer_profile_id).to eq "cus_A123"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Taler" do
|
||||
|
||||
@@ -5,189 +5,72 @@ require 'system_helper'
|
||||
RSpec.describe 'Multilingual' do
|
||||
include AuthenticationHelper
|
||||
include WebHelper
|
||||
include ShopWorkflow
|
||||
include UIComponentHelper
|
||||
include CookieHelper
|
||||
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'has three locales available' do
|
||||
expect(Rails.application.config.i18n[:default_locale]).to eq 'en'
|
||||
expect(Rails.application.config.i18n[:locale]).to eq 'en'
|
||||
expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es', 'pt']
|
||||
expect(Rails.application.config.i18n[:default_locale]).to eq 'en_TST'
|
||||
expect(Rails.application.config.i18n[:locale]).to eq 'en_TST'
|
||||
expect(Rails.application.config.i18n[:available_locales]).to eq ['en_TST', 'es', 'pt', 'en']
|
||||
end
|
||||
|
||||
it '18n-js fallsback to default language' do
|
||||
# in backend it doesn't until we change enforce_available_locales to `true`
|
||||
it 'can switch language by params' do
|
||||
visit root_path
|
||||
set_i18n_locale('it')
|
||||
expect(pick_i18n_locale).to eq 'en_TST'
|
||||
expect(get_i18n_translation('label_shops')).to eq 'Shops'
|
||||
expect(cookies_name).not_to include('locale')
|
||||
expect(page).to have_content 'SHOPS'
|
||||
|
||||
visit root_path(locale: 'es')
|
||||
expect(pick_i18n_locale).to eq 'es'
|
||||
expect(get_i18n_translation('label_shops')).to eq 'Tiendas'
|
||||
expect_menu_and_cookie_in_es
|
||||
|
||||
# it is not in the list of available of available_locales
|
||||
visit root_path(locale: 'it')
|
||||
expect(pick_i18n_locale).to eq 'es'
|
||||
expect(get_i18n_translation('label_shops')).to eq 'Tiendas'
|
||||
expect_menu_and_cookie_in_es
|
||||
end
|
||||
|
||||
context 'can switch language by params' do
|
||||
it 'in root path' do
|
||||
visit root_path
|
||||
expect(pick_i18n_locale).to eq 'en'
|
||||
expect(get_i18n_translation('label_shops')).to eq 'Shops'
|
||||
expect(cookies_name).not_to include('locale')
|
||||
expect(page).to have_content 'SHOPS'
|
||||
it 'updates user locale from cookie if it is empty' do
|
||||
visit root_path(locale: 'es')
|
||||
|
||||
visit root_path(locale: 'es')
|
||||
expect(pick_i18n_locale).to eq 'es'
|
||||
expect(get_i18n_translation('label_shops')).to eq 'Tiendas'
|
||||
expect_menu_and_cookie_in_es
|
||||
expect_menu_and_cookie_in_es
|
||||
expect(user.locale).to be_nil
|
||||
login_as user
|
||||
visit root_path
|
||||
|
||||
# it is not in the list of available of available_locales
|
||||
visit root_path(locale: 'it')
|
||||
expect(pick_i18n_locale).to eq 'es'
|
||||
expect(get_i18n_translation('label_shops')).to eq 'Tiendas'
|
||||
expect_menu_and_cookie_in_es
|
||||
end
|
||||
expect_menu_and_cookie_in_es
|
||||
|
||||
context 'with a product in the cart' do
|
||||
let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
|
||||
let!(:order_cycle) {
|
||||
create(:simple_order_cycle, distributors: [distributor], variants: [product.variants.first])
|
||||
}
|
||||
let(:product) { create(:simple_product) }
|
||||
let(:order) { create(:order, order_cycle:, distributor:) }
|
||||
# The user's locale is not changed if the language was chosen before
|
||||
# login. Is it a bug or a feature? Probably not important...
|
||||
expect(user.reload.locale).to eq nil
|
||||
|
||||
before do
|
||||
pick_order order
|
||||
add_product_to_cart order, product, quantity: 1
|
||||
end
|
||||
visit root_path(locale: 'es')
|
||||
expect(user.reload.locale).to eq 'es'
|
||||
|
||||
it "in the cart page" do
|
||||
visit main_app.cart_path(locale: 'es')
|
||||
logout
|
||||
|
||||
expect_menu_and_cookie_in_es
|
||||
expect(page).to have_content 'Precio'
|
||||
end
|
||||
|
||||
it "visiting checkout as a guest user" do
|
||||
visit checkout_path(locale: 'es')
|
||||
|
||||
expect_menu_and_cookie_in_es
|
||||
expect(page).to have_content 'Iniciar sesión'
|
||||
end
|
||||
end
|
||||
expect_menu_and_cookie_in_es
|
||||
expect(page).to have_content '¿Estás interesada en entrar en Open Food Network?'
|
||||
end
|
||||
|
||||
context 'with user' do
|
||||
let(:user) { create(:user) }
|
||||
it "allows switching language via the main navigation" do
|
||||
visit root_path
|
||||
|
||||
it 'updates user locale from cookie if it is empty' do
|
||||
visit root_path(locale: 'es')
|
||||
expect(page).to have_content 'SHOPS'
|
||||
|
||||
expect_menu_and_cookie_in_es
|
||||
expect(user.locale).to be_nil
|
||||
login_as user
|
||||
visit root_path
|
||||
find('.language-switcher').click
|
||||
within '.language-switcher .dropdown' do
|
||||
expect(page).not_to have_link 'English'
|
||||
expect(page).to have_link 'Español'
|
||||
|
||||
expect_menu_and_cookie_in_es
|
||||
click_link 'Español'
|
||||
end
|
||||
|
||||
it 'updates user locale and stays in cookie after logout' do
|
||||
login_as user
|
||||
|
||||
visit root_path(locale: 'es')
|
||||
user.reload
|
||||
|
||||
expect(user.locale).to eq 'es'
|
||||
|
||||
logout
|
||||
|
||||
expect_menu_and_cookie_in_es
|
||||
expect(page).to have_content '¿Estás interesada en entrar en Open Food Network?'
|
||||
end
|
||||
|
||||
context "visiting checkout as logged user" do
|
||||
let!(:zone) { create(:zone_with_member) }
|
||||
let(:supplier) { create(:supplier_enterprise) }
|
||||
let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) }
|
||||
let(:product) {
|
||||
create(:taxed_product, supplier_id: supplier.id, price: 10, zone:)
|
||||
}
|
||||
let(:variant) { product.variants.first }
|
||||
let!(:order_cycle) {
|
||||
create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor],
|
||||
coordinator: create(:distributor_enterprise),
|
||||
variants: [variant])
|
||||
}
|
||||
|
||||
let(:free_shipping) {
|
||||
create(:shipping_method, require_ship_address: false)
|
||||
}
|
||||
let!(:payment) {
|
||||
create(:payment_method, distributors: [distributor],
|
||||
name: "Payment")
|
||||
}
|
||||
let(:order) {
|
||||
create(:order_ready_for_confirmation, distributor:)
|
||||
}
|
||||
before do
|
||||
pick_order order
|
||||
login_as user
|
||||
end
|
||||
|
||||
it "on the details step" do
|
||||
visit checkout_step_path(:details, locale: 'es')
|
||||
|
||||
expect_menu_and_cookie_in_es
|
||||
expect(page).to have_content "Sus detalles"
|
||||
end
|
||||
|
||||
it "on the payment step" do
|
||||
visit checkout_step_path(:payment, locale: 'es')
|
||||
|
||||
expect_menu_and_cookie_in_es
|
||||
expect(page).to have_content "Puede revisar y confirmar su pedido"
|
||||
end
|
||||
|
||||
it "on the summary step" do
|
||||
visit checkout_step_path(:summary, locale: 'es')
|
||||
|
||||
expect_menu_and_cookie_in_es
|
||||
expect(page).to have_content "Detalles de entrega"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "using the language switcher UI" do
|
||||
context "when there is only one language available" do
|
||||
before do
|
||||
allow(ENV).to receive(:[]).and_call_original
|
||||
allow(ENV).to receive(:[]).with("LOCALE").and_return("en")
|
||||
allow(ENV).to receive(:[]).with("AVAILABLE_LOCALES").and_return("en")
|
||||
end
|
||||
|
||||
it "hides the dropdown language menu" do
|
||||
visit root_path
|
||||
expect(page).not_to have_css 'ul.right li.language-switcher.has-dropdown'
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are multiple languages available" do
|
||||
before do
|
||||
allow(ENV).to receive(:[]).and_call_original
|
||||
allow(ENV).to receive(:[]).with("LOCALE").and_return("en")
|
||||
allow(ENV).to receive(:[]).with("AVAILABLE_LOCALES").and_return("en,es")
|
||||
end
|
||||
|
||||
it "allows switching language via the main navigation" do
|
||||
visit root_path
|
||||
|
||||
expect(page).to have_content 'SHOPS'
|
||||
|
||||
find('.language-switcher').click
|
||||
within '.language-switcher .dropdown' do
|
||||
expect(page).not_to have_link 'English', href: '/locales/en'
|
||||
expect(page).to have_link 'Español', href: '/locales/es'
|
||||
|
||||
find('li a[href="/locales/es"]').click
|
||||
end
|
||||
|
||||
expect_menu_and_cookie_in_es
|
||||
end
|
||||
end
|
||||
expect_menu_and_cookie_in_es
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -3,221 +3,34 @@
|
||||
require 'system_helper'
|
||||
|
||||
RSpec.describe "Check out with Stripe" do
|
||||
include AuthenticationHelper
|
||||
include ShopWorkflow
|
||||
include CheckoutRequestsHelper
|
||||
include StripeHelper
|
||||
include StripeStubs
|
||||
|
||||
let(:distributor) { create(:distributor_enterprise) }
|
||||
let!(:order_cycle) {
|
||||
create(:simple_order_cycle, distributors: [distributor], variants: [variant])
|
||||
}
|
||||
let(:product) { create(:product, price: 10) }
|
||||
let(:variant) { product.variants.first }
|
||||
let(:order) {
|
||||
create(:order, order_cycle:, distributor:, bill_address_id: nil,
|
||||
ship_address_id: nil)
|
||||
}
|
||||
|
||||
let(:shipping_with_fee) {
|
||||
create(:shipping_method, require_ship_address: false, name: "Donkeys",
|
||||
calculator: Calculator::FlatRate.new(preferred_amount: 4.56))
|
||||
}
|
||||
let(:free_shipping) { create(:shipping_method) }
|
||||
let!(:check_with_fee) {
|
||||
create(:payment_method, distributors: [distributor],
|
||||
calculator: Calculator::FlatRate.new(preferred_amount: 5.67))
|
||||
}
|
||||
|
||||
around do |example|
|
||||
with_stripe_setup { example.run }
|
||||
end
|
||||
|
||||
before do
|
||||
stripe_enable
|
||||
pick_order order
|
||||
add_product_to_cart order, product
|
||||
distributor.shipping_methods << [shipping_with_fee, free_shipping]
|
||||
end
|
||||
|
||||
pending "using Stripe SCA" do
|
||||
let!(:stripe_account) { create(:stripe_account, enterprise: distributor) }
|
||||
let!(:stripe_sca_payment_method) {
|
||||
create(:stripe_sca_payment_method, distributors: [distributor])
|
||||
}
|
||||
let!(:shipping_method) { create(:shipping_method) }
|
||||
let(:error_message) { "Card was declined: insufficient funds." }
|
||||
|
||||
before do
|
||||
stub_payment_intent_get_request
|
||||
stub_payment_methods_post_request
|
||||
end
|
||||
|
||||
describe "using Stripe SCA" do
|
||||
context "with guest checkout" do
|
||||
before do
|
||||
stub_retrieve_payment_method_request("pm_123")
|
||||
stub_list_customers_request(email: order.user.email, response: {})
|
||||
stub_get_customer_payment_methods_request(customer: "cus_A456", response: {})
|
||||
end
|
||||
|
||||
context "when the card is accepted" do
|
||||
before do
|
||||
stub_payment_intents_post_request(order:)
|
||||
stub_successful_capture_request order:
|
||||
end
|
||||
|
||||
it "completes checkout successfully" do
|
||||
checkout_with_stripe
|
||||
|
||||
expect(page).to have_content "Confirmed"
|
||||
expect(page.find("#amount-paid").text).to have_content "$19.99"
|
||||
|
||||
expect(order.reload.completed?).to eq true
|
||||
expect(order.payments.first.state).to eq "completed"
|
||||
end
|
||||
it "completes checkout successfully"
|
||||
end
|
||||
|
||||
context "when the card is rejected" do
|
||||
before do
|
||||
stub_payment_intents_post_request(order:)
|
||||
stub_failed_capture_request order:, response: { message: error_message }
|
||||
end
|
||||
|
||||
it "shows an error message from the Stripe response" do
|
||||
checkout_with_stripe
|
||||
|
||||
expect(page).to have_content error_message
|
||||
expect(order.reload.state).to eq "cart"
|
||||
expect(order.payments.first.state).to eq "failed"
|
||||
end
|
||||
it "shows an error message from the Stripe response"
|
||||
end
|
||||
|
||||
context "when the card needs extra SCA authorization" do
|
||||
before do
|
||||
stripe_redirect_url = checkout_path(payment_intent: "pi_123")
|
||||
stub_payment_intents_post_request_with_redirect order:,
|
||||
redirect_url: stripe_redirect_url
|
||||
end
|
||||
|
||||
describe "and the authorization succeeds" do
|
||||
before do
|
||||
stub_successful_capture_request order:
|
||||
end
|
||||
|
||||
it "completes checkout successfully" do
|
||||
checkout_with_stripe
|
||||
|
||||
# We make stripe return stripe_redirect_url (which is already sending the user back
|
||||
# to the checkout) as if the authorization was done. We can then control the actual
|
||||
# authorization or failure of the payment through the mock
|
||||
# stub_successful_capture_request
|
||||
|
||||
expect(page).to have_content "Confirmed"
|
||||
expect(order.reload.completed?).to eq true
|
||||
expect(order.payments.first.state).to eq "completed"
|
||||
end
|
||||
it "completes checkout successfully"
|
||||
end
|
||||
|
||||
describe "and the authorization fails" do
|
||||
before do
|
||||
stub_failed_capture_request order:, response: { message: error_message }
|
||||
end
|
||||
|
||||
it "shows an error message from the Stripe response" do
|
||||
checkout_with_stripe
|
||||
|
||||
# We make stripe return stripe_redirect_url (which is already sending the user back to
|
||||
# the checkout) as if the authorization was done. We can then control the actual
|
||||
# authorization or failure of the payment through the mock stub_failed_capture_request
|
||||
expect(page).to have_content error_message
|
||||
expect(order.reload.state).to eq "cart"
|
||||
expect(order.payments.first.state).to eq "failed"
|
||||
end
|
||||
it "shows an error message from the Stripe response"
|
||||
end
|
||||
end
|
||||
|
||||
context "with multiple payment attempts; one failed and one succeeded" do
|
||||
before do
|
||||
stub_payment_intents_post_request order:
|
||||
end
|
||||
|
||||
it "records failed payment attempt and allows order completion" do
|
||||
# First payment attempt is rejected
|
||||
stub_failed_capture_request(order:, response: { message: error_message })
|
||||
checkout_with_stripe
|
||||
expect(page).to have_content error_message
|
||||
|
||||
expect(order.reload.payments.count).to eq 1
|
||||
expect(order.state).to eq "cart"
|
||||
expect(order.payments.first.state).to eq "failed"
|
||||
|
||||
# Second payment attempt is accepted
|
||||
stub_successful_capture_request(order:)
|
||||
place_order
|
||||
expect(page).to have_content "Confirmed"
|
||||
|
||||
expect(order.reload.payments.count).to eq 2
|
||||
expect(order.state).to eq "complete"
|
||||
expect(order.payments.last.state).to eq "completed"
|
||||
end
|
||||
it "records failed payment attempt and allows order completion"
|
||||
end
|
||||
end
|
||||
|
||||
context "with a logged in user" do
|
||||
let(:user) { order.user }
|
||||
|
||||
before do
|
||||
login_as user
|
||||
end
|
||||
|
||||
context "saving a card and re-using it" do
|
||||
before do
|
||||
stub_retrieve_payment_method_request("pm_123")
|
||||
stub_list_customers_request(email: order.user.email, response: {})
|
||||
stub_get_customer_payment_methods_request(customer: "cus_A456", response: {})
|
||||
stub_get_customer_payment_methods_request(customer: "cus_A123", response: {})
|
||||
stub_payment_methods_post_request(
|
||||
request: { payment_method: "pm_123", customer: "cus_A123" },
|
||||
response: { pm_id: "pm_123" }
|
||||
)
|
||||
stub_add_metadata_request(payment_method: "pm_123", response: {})
|
||||
stub_payment_intents_post_request(order:)
|
||||
stub_successful_capture_request(order:)
|
||||
stub_customers_post_request email: "test@test.com" # First checkout with default details
|
||||
stub_customers_post_request email: user.email # Second checkout with saved user details
|
||||
stub_payment_method_attach_request
|
||||
end
|
||||
|
||||
it "allows saving a card and re-using it" do
|
||||
checkout_with_stripe guest_checkout: false, remember_card: true
|
||||
|
||||
expect(page).to have_content "Confirmed"
|
||||
expect(order.reload.completed?).to eq true
|
||||
expect(order.payments.first.state).to eq "completed"
|
||||
|
||||
# Verify card has been saved with correct stripe IDs
|
||||
user_credit_card = order.reload.user.credit_cards.first
|
||||
expect(user_credit_card.gateway_payment_profile_id).to eq "pm_123"
|
||||
expect(user_credit_card.gateway_customer_profile_id).to eq "cus_A123"
|
||||
|
||||
# Prepare a second order
|
||||
new_order = create(:order, user:, order_cycle:,
|
||||
distributor:, bill_address_id: nil,
|
||||
ship_address_id: nil)
|
||||
pick_order(new_order)
|
||||
add_product_to_cart(new_order, product, quantity: 10)
|
||||
stub_payment_intents_post_request order: new_order
|
||||
stub_successful_capture_request order: new_order
|
||||
|
||||
# Checkout with saved card
|
||||
visit checkout_path
|
||||
choose free_shipping.name
|
||||
choose stripe_sca_payment_method.name
|
||||
expect(page).to have_content "Use a saved card"
|
||||
expect(page).to have_select 'selected_card', selected: "Visa x-4242 Exp:10/2050"
|
||||
place_order
|
||||
end
|
||||
it "allows saving a card and re-using it"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user