diff --git a/.github/actions/e2e/env-setup/action.yml b/.github/actions/e2e/env-setup/action.yml index e1dbd310239..0296fc6eea3 100644 --- a/.github/actions/e2e/env-setup/action.yml +++ b/.github/actions/e2e/env-setup/action.yml @@ -30,7 +30,7 @@ runs: uses: actions/cache@v4 with: path: ./vendor - key: ${{ runner.os }}-vendor-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} # Cache node dependencies - name: Cache node dependencies diff --git a/.github/actions/setup-repo/action.yml b/.github/actions/setup-repo/action.yml index d8de18c7d8d..2e1098a6d19 100644 --- a/.github/actions/setup-repo/action.yml +++ b/.github/actions/setup-repo/action.yml @@ -14,7 +14,7 @@ runs: uses: actions/cache@v4 with: path: ~/.cache/composer/ - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} - name: "Set up PHP" uses: ./.github/actions/setup-php diff --git a/.github/workflows/check-changelog.yml b/.github/workflows/check-changelog.yml index 682710edbdd..3aa3936ca64 100644 --- a/.github/workflows/check-changelog.yml +++ b/.github/workflows/check-changelog.yml @@ -22,7 +22,7 @@ jobs: uses: actions/cache@v4 with: path: ~/.cache/composer/ - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} # setup PHP, but without debug extensions for reasonable performance - name: "Set up PHP" uses: ./.github/actions/setup-php diff --git a/.github/workflows/compatibility.yml b/.github/workflows/compatibility.yml index 02a2d7d4c7e..e1b7279b70f 100644 --- a/.github/workflows/compatibility.yml +++ b/.github/workflows/compatibility.yml @@ -45,7 +45,7 @@ jobs: - uses: actions/cache@v4 with: path: ~/.cache/composer/ - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} # setup PHP, but without debug extensions for reasonable performance - uses: shivammathur/setup-php@v2 with: @@ -54,7 +54,7 @@ jobs: coverage: none # run CI checks - run: bash bin/run-ci-tests.bash - + generate-wc-compat-beta-matrix: name: "Generate the matrix for compatibility-woocommerce-beta dynamically" runs-on: ubuntu-latest @@ -86,7 +86,7 @@ jobs: - uses: actions/cache@v4 with: path: ~/.cache/composer/ - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} # setup PHP, but without debug extensions for reasonable performance - uses: shivammathur/setup-php@v2 with: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 79ff0d7a01f..1728e6f9fee 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -30,7 +30,7 @@ jobs: - uses: actions/cache@v4 with: path: ~/.cache/composer/ - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} # setup PHP, but without debug extensions for reasonable performance - uses: shivammathur/setup-php@v2 with: diff --git a/.github/workflows/i18n-weekly-release.yml b/.github/workflows/i18n-weekly-release.yml index 2c7f0fa0396..bd87284be4e 100644 --- a/.github/workflows/i18n-weekly-release.yml +++ b/.github/workflows/i18n-weekly-release.yml @@ -21,7 +21,7 @@ jobs: - uses: actions/cache@v4 with: path: ~/.cache/composer/ - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} - uses: actions/cache@v4 with: path: ~/.npm/ @@ -33,7 +33,7 @@ jobs: run: | npm ci npm run build - + if [[ ! -f woocommerce-payments.zip ]]; then echo "Failed to create release zip" exit 1 diff --git a/.github/workflows/js-lint-test.yml b/.github/workflows/js-lint-test.yml index b3797f4dae0..461984d93da 100644 --- a/.github/workflows/js-lint-test.yml +++ b/.github/workflows/js-lint-test.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/cache@v4 with: path: ~/.cache/composer/ - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} - uses: actions/cache@v4 with: path: ~/.npm/ diff --git a/.github/workflows/php-lint-test.yml b/.github/workflows/php-lint-test.yml index de15390609e..3d4ca36b9ed 100644 --- a/.github/workflows/php-lint-test.yml +++ b/.github/workflows/php-lint-test.yml @@ -25,7 +25,7 @@ jobs: - uses: actions/cache@v4 with: path: ~/.cache/composer/ - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} # setup PHP, but without debug extensions for reasonable performance - name: "Set up PHP" uses: ./.github/actions/setup-php @@ -59,7 +59,7 @@ jobs: - uses: actions/cache@v4 with: path: ~/.cache/composer/ - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.json') }}-${{ hashFiles('composer.lock') }} - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} diff --git a/assets/css/admin.css b/assets/css/admin.css index baf66dcee88..7b6d75945de 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -155,11 +155,93 @@ padding-top: 2px; } +/* WCPay Fraud Risk Level meta box */ +.wcpay-fraud-risk-level { + border-bottom: 1px solid #ddd; + padding: 8px 12px; +} + +.wcpay-fraud-risk-level > p { + margin: 0; +} + +.wcpay-fraud-risk-level__title { + font-weight: 600; +} + +.wcpay-fraud-risk-level__bar { + display: grid; + gap: 4px; + grid-template-columns: 50% auto; + margin: 6px 0 8px; +} + +.wcpay-fraud-risk-level__bar::after, +.wcpay-fraud-risk-level__bar::before { + background-color: #bbb; + content: ''; + border-radius: 4px; + height: 4px; +} + +.wcpay-fraud-risk-level--normal .wcpay-fraud-risk-level__title { + color: #008a20; +} + +.wcpay-fraud-risk-level--normal .wcpay-fraud-risk-level__bar { + grid-template-columns: 15% auto; +} + +.wcpay-fraud-risk-level--normal .wcpay-fraud-risk-level__bar::before { + background-color: #008a20; +} + +.wcpay-fraud-risk-level--elevated .wcpay-fraud-risk-level__title { + color: #b16202; +} + +.wcpay-fraud-risk-level--elevated .wcpay-fraud-risk-level__bar { + grid-template-columns: 60% auto; +} + +.wcpay-fraud-risk-level--elevated .wcpay-fraud-risk-level__bar::before { + background-color: #b16202; +} + +.wcpay-fraud-risk-level--highest .wcpay-fraud-risk-level__bar::before { + background-color: #b32d2e; +} + +.wcpay-fraud-risk-level--highest .wcpay-fraud-risk-level__bar { + grid-template-columns: 100% auto; +} + +.wcpay-fraud-risk-level--highest .wcpay-fraud-risk-level__bar::before { + background-color: #b32d2e; +} + +/* WCPay Fraud Risk Action meta box */ +#wcpay-order-fraud-and-risk-meta-box div.inside { + margin-top: 0; + padding: 0; +} + +.wcpay-fraud-risk-action { + padding: 8px 12px 12px; +} + +.wcpay-fraud-risk-action > p { + margin: 0 0 6px; +} + +.wcpay-fraud-risk-action > p:last-child { + margin-bottom: 0; +} + .wcpay-fraud-risk-meta-allow, .wcpay-fraud-risk-meta-review, .wcpay-fraud-risk-meta-blocked { font-weight: 600; - font-size: 14px; } .wcpay-fraud-risk-meta-allow img { diff --git a/assets/css/success.css b/assets/css/success.css index 8ada2af0ee6..f11e45dd18a 100644 --- a/assets/css/success.css +++ b/assets/css/success.css @@ -3,13 +3,13 @@ align-items: center; flex-wrap: wrap; line-height: 1; + padding-top: 4px; } .wc-payment-gateway-method-logo-wrapper img { margin-right: 0.5rem; - padding-top: 4px; } -.wc-payment-gateway-method-logo-wrapper.wc-payment-bnpl-logo img { - max-height: 30px; +.wc-payment-gateway-method-logo-wrapper.wc-payment-lpm-logo img { + max-height: 26px; } diff --git a/assets/css/success.rtl.css b/assets/css/success.rtl.css index 16c136a0b1e..c0778375319 100644 --- a/assets/css/success.rtl.css +++ b/assets/css/success.rtl.css @@ -3,13 +3,13 @@ align-items: center; flex-wrap: wrap; line-height: 1; + padding-top: 4px; } .wc-payment-gateway-method-logo-wrapper img { margin-left: 0.5rem; - padding-top: 4px; } -.wc-payment-gateway-method-logo-wrapper.wc-payment-bnpl-logo img { - max-height: 30px; +.wc-payment-gateway-method-logo-wrapper.wc-payment-lpm-logo img { + max-height: 26px; } diff --git a/changelog.txt b/changelog.txt index 3e68c78c9f1..745c2fe24be 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,39 @@ *** WooPayments Changelog *** += 8.5.0 - 2024-11-13 = +* Add - Add country-specific test card numbers for credit card testing +* Add - Add risk level information to the fraud and risk box on the order details page. +* Add - Add support for allowedShippingCountries in Express Checkout Element. +* Fix - Avoid PHP warnings for requests with an empty path. +* Fix - BNPL methods now work properly in Pay for Order when they are available. Default values are also provided when available. +* Fix - fix: payment method icon alt text +* Fix - Fix compatibility issues with CustomSelectControl component styles for WordPress 6.7 +* Fix - Fix duplicate saving of 3DS card entry after checkout +* Fix - Fixed single product page view tracks when BNPL and PRB payment methods are inactive. +* Fix - Fix PMME appearance in checkout +* Fix - Fix settings display on the advanced fraud protection page. +* Fix - Fix WooPay button preview in plugin settings. +* Fix - Fix WooPay duplicated Save my info section. +* Fix - Include missing scripts that handle refunds for non credit card payments in the order details page. +* Fix - Introducing consistency in colors for deposits across pages +* Fix - Prevent dead space on product pages when no BNPL offers are available. +* Fix - Provide backwards-compatible method for retrieving the multi-currency instance. +* Fix - Register Expresss Checkout block only when enabled in the settings +* Fix - Remove unnecessary '.woocommerce-table' css overrides to fix WC Analytics styling and a11y issues +* Fix - Use 'Withdrawal' and 'Deducted' labels when referring to withdrawal deposits, to more accurately communicate the type of transaction that has occurred +* Update - Add in-memory cache fallback for our database-cached objects in case of database write failures. +* Update - Decoupled Multi-currency module from gateway dependencies. +* Update - Improvements to events during onboarding flow. +* Update - Refactor loadStripe for Express Checkouts. +* Update - Rename 'deposit' to 'payout' across various places in the WooPayments admin UI, docs and doc URLs. +* Update - update: payment method "test mode" label at checkout to be displayed only when payment method is selected +* Update - update: show LPM payment method icon on order success page +* Update - Use preview versions of the actual ECE buttons in the Block editor. +* Update - When tracking is enabled, send a tracks event when the merchant is redirected to a Stripe Capital offer. +* Dev - Add Jest tests for the disputed order notices +* Dev - Add unit tests for the Capital Loans page component. +* Dev - Bump WC tested up to version to 9.4.0 + = 8.4.0 - 2024-10-23 = * Add - Add test mode badge to classic checkout and add payment method. * Add - Using Floating Labels with Stripe Appearance API for Blocks Checkout diff --git a/client/additional-methods-setup/upe-preview-methods-selector/add-payment-methods-task.js b/client/additional-methods-setup/upe-preview-methods-selector/add-payment-methods-task.js index 76a2f3baa71..fbc23b63b67 100644 --- a/client/additional-methods-setup/upe-preview-methods-selector/add-payment-methods-task.js +++ b/client/additional-methods-setup/upe-preview-methods-selector/add-payment-methods-task.js @@ -36,7 +36,7 @@ import PaymentMethodCheckbox from '../../components/payment-methods-checkboxes/p import { LoadableBlock } from '../../components/loadable'; import LoadableSettingsSection from '../../settings/loadable-settings-section'; import CurrencyInformationForMethods from './currency-information-for-methods'; -import { getMissingCurrenciesTooltipMessage } from 'wcpay/multi-currency/missing-currencies-message'; +import { getMissingCurrenciesTooltipMessage } from 'multi-currency/interface/functions'; import { upeCapabilityStatuses, upeMethods } from '../constants'; import paymentMethodsMap from '../../payment-methods-map'; import ConfirmPaymentMethodActivationModal from 'wcpay/settings/payment-methods-list/activation-modal'; diff --git a/client/additional-methods-setup/upe-preview-methods-selector/currency-information-for-methods.js b/client/additional-methods-setup/upe-preview-methods-selector/currency-information-for-methods.js index f4e1fc02cbc..9639a729c8b 100644 --- a/client/additional-methods-setup/upe-preview-methods-selector/currency-information-for-methods.js +++ b/client/additional-methods-setup/upe-preview-methods-selector/currency-information-for-methods.js @@ -9,11 +9,11 @@ import interpolateComponents from '@automattic/interpolate-components'; /** * Internal dependencies */ +import { useAccountDomesticCurrency } from '../../data'; import { - useAccountDomesticCurrency, useCurrencies, useEnabledCurrencies, -} from '../../data'; +} from 'multi-currency/interface/data'; import WCPaySettingsContext from '../../settings/wcpay-settings-context'; import InlineNotice from 'components/inline-notice'; import PaymentMethodsMap from '../../payment-methods-map'; diff --git a/client/additional-methods-setup/upe-preview-methods-selector/test/add-payment-methods-task.test.js b/client/additional-methods-setup/upe-preview-methods-selector/test/add-payment-methods-task.test.js index 3339e812975..3a12347327f 100644 --- a/client/additional-methods-setup/upe-preview-methods-selector/test/add-payment-methods-task.test.js +++ b/client/additional-methods-setup/upe-preview-methods-selector/test/add-payment-methods-task.test.js @@ -22,11 +22,14 @@ import { useEnabledPaymentMethodIds, useGetPaymentMethodStatuses, useSettings, - useCurrencies, - useEnabledCurrencies, useManualCapture, useAccountDomesticCurrency, } from '../../../data'; +import { + useCurrencies, + useEnabledCurrencies, +} from 'multi-currency/interface/data'; + import WCPaySettingsContext from '../../../settings/wcpay-settings-context'; import { upeCapabilityStatuses } from 'wcpay/additional-methods-setup/constants'; @@ -34,13 +37,16 @@ jest.mock( '../../../data', () => ( { useGetAvailablePaymentMethodIds: jest.fn(), useEnabledPaymentMethodIds: jest.fn(), useSettings: jest.fn(), - useCurrencies: jest.fn(), - useEnabledCurrencies: jest.fn(), useGetPaymentMethodStatuses: jest.fn(), useManualCapture: jest.fn(), useAccountDomesticCurrency: jest.fn(), } ) ); +jest.mock( 'multi-currency/interface/data', () => ( { + useCurrencies: jest.fn(), + useEnabledCurrencies: jest.fn(), +} ) ); + jest.mock( '@wordpress/a11y', () => ( { ...jest.requireActual( '@wordpress/a11y' ), speak: jest.fn(), diff --git a/client/additional-methods-setup/upe-preview-methods-selector/test/currency-information-for-methods.test.js b/client/additional-methods-setup/upe-preview-methods-selector/test/currency-information-for-methods.test.js index fd473249eb7..cc2abefe96d 100644 --- a/client/additional-methods-setup/upe-preview-methods-selector/test/currency-information-for-methods.test.js +++ b/client/additional-methods-setup/upe-preview-methods-selector/test/currency-information-for-methods.test.js @@ -7,18 +7,21 @@ import { render, screen } from '@testing-library/react'; /** * Internal dependencies */ +import { useAccountDomesticCurrency } from '../../../data'; import { useCurrencies, useEnabledCurrencies, - useAccountDomesticCurrency, -} from 'wcpay/data'; +} from 'multi-currency/interface/data'; import CurrencyInformationForMethods from '../currency-information-for-methods'; import WCPaySettingsContext from '../../../settings/wcpay-settings-context'; -jest.mock( 'wcpay/data', () => ( { +jest.mock( '../../../data', () => ( { + useAccountDomesticCurrency: jest.fn(), +} ) ); + +jest.mock( 'multi-currency/interface/data', () => ( { useCurrencies: jest.fn(), useEnabledCurrencies: jest.fn(), - useAccountDomesticCurrency: jest.fn(), } ) ); jest.mock( '@wordpress/a11y', () => ( { diff --git a/client/additional-methods-setup/wizard/task-item.scss b/client/additional-methods-setup/wizard/task-item.scss index c2b7dbb5ec6..ae24c06ac08 100644 --- a/client/additional-methods-setup/wizard/task-item.scss +++ b/client/additional-methods-setup/wizard/task-item.scss @@ -117,6 +117,22 @@ } } + &__visible-description-element { + position: absolute; + margin-left: 40px; + margin-top: 0; + margin-bottom: 1em; + + &.is-muted-color { + color: $gray-700; + } + + .components-external-link svg { + width: 1em; + height: 1em; + } + } + .add-payment-methods-task { &__payment-selector { &-wrapper { diff --git a/client/additional-methods-setup/wizard/task-item.tsx b/client/additional-methods-setup/wizard/task-item.tsx index f1c7ba4177e..a0ec6169bae 100644 --- a/client/additional-methods-setup/wizard/task-item.tsx +++ b/client/additional-methods-setup/wizard/task-item.tsx @@ -16,6 +16,7 @@ interface WizardTaskItemProps { title: string; index: number; className?: string; + visibleDescription?: string; } const WizardTaskItem: React.FC< WizardTaskItemProps > = ( { @@ -23,6 +24,7 @@ const WizardTaskItem: React.FC< WizardTaskItemProps > = ( { title, index, className, + visibleDescription, } ) => { const { isCompleted, isActive } = useContext( WizardTaskContext ); @@ -51,6 +53,16 @@ const WizardTaskItem: React.FC< WizardTaskItemProps > = ( { { title } + { visibleDescription && ! isActive && ( + + { visibleDescription } + + ) }
{ children }
); diff --git a/client/capital/index.tsx b/client/capital/index.tsx index 8d1ab3f4741..81e76ad91b4 100644 --- a/client/capital/index.tsx +++ b/client/capital/index.tsx @@ -15,7 +15,10 @@ import Page from 'components/page'; import { TestModeNotice } from 'components/test-mode-notice'; import ErrorBoundary from 'components/error-boundary'; import ActiveLoanSummary from 'components/active-loan-summary'; -import { formatExplicitCurrency, isZeroDecimalCurrency } from 'utils/currency'; +import { + formatExplicitCurrency, + isZeroDecimalCurrency, +} from 'multi-currency/interface/functions'; import { CapitalLoan } from 'data/capital/types'; import ClickableCell from 'components/clickable-cell'; import Chip from 'components/chip'; diff --git a/client/capital/test/__snapshots__/index.test.tsx.snap b/client/capital/test/__snapshots__/index.test.tsx.snap new file mode 100644 index 00000000000..2b146dd5714 --- /dev/null +++ b/client/capital/test/__snapshots__/index.test.tsx.snap @@ -0,0 +1,496 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CapitalPage renders the TableCard component with loan data 1`] = ` +
+
+
+
+ Viewing test loans. To view live loans, disable test mode in + + WooPayments settings + + . +
+
+
+
+
+
+ Active loan overview +
+
+
+
+
+
+
+ Total repaid +
+
+ + $0.00 + + of $1,100.00 +
+
+
+
+ Repaid this period (until Dec 27, 2024) +
+
+ + $0.00 + + of $122.23 minimum +
+
+
+
+
+
+ Loan disbursed +
+
+ Oct 21, 2024 +
+
+
+
+ Loan amount +
+
+ $1,000.00 +
+
+
+
+ Fixed fee +
+
+ $100.00 +
+
+
+
+ Withhold rate +
+
+ 15 + % +
+
+
+
+ First paydown +
+
+ Oct 28, 2024 +
+
+
+
+
+ @@ -407,14 +455,14 @@ exports[`Suspended Deposit Notice Renders Component Renders 1`] = ` data-wp-c16t="true" data-wp-component="FlexItem" > - Your deposits are + Your payouts are temporarily suspended . Learn more diff --git a/client/components/deposits-overview/test/index.tsx b/client/components/deposits-overview/test/index.tsx index 4853aff7bf5..edaa068a100 100644 --- a/client/components/deposits-overview/test/index.tsx +++ b/client/components/deposits-overview/test/index.tsx @@ -90,6 +90,15 @@ const mockDeposits = [ bankAccount: 'MOCK BANK •••• 1234 (USD)', currency: 'USD', } as CachedDeposit, + { + id: 'po_mock3', + date: '2020-01-04 17:46:02', + type: 'withdrawal', + amount: 4000, + status: 'paid', + bankAccount: 'MOCK BANK •••• 1234 (USD)', + currency: 'USD', + } as CachedDeposit, ]; // Creates a mock Overview object for the given currency code and balance amounts. @@ -257,8 +266,8 @@ describe( 'Deposits Overview information', () => { const { container, getByText } = render( ); // Check that the button and link is rendered. - getByText( 'View full deposits history' ); - getByText( 'Change deposit schedule' ); + getByText( 'View full payout history' ); + getByText( 'Change payout schedule' ); expect( container ).toMatchSnapshot(); } ); @@ -295,7 +304,7 @@ describe( 'Deposits Overview information', () => { setSelectedCurrency: mockSetSelectedCurrency, } ); const { getByText, queryByText } = render( ); - getByText( /Your first deposit is held for/, { + getByText( /Your first payout is held for/, { ignore: '.a11y-speak-region', } ); expect( queryByText( 'Change deposit schedule' ) ).toBeFalsy(); @@ -318,10 +327,10 @@ describe( 'Deposits Overview information', () => { const { getByText, queryByText } = render( ); - getByText( /Your deposits are temporarily suspended/ ); + getByText( /Your payouts are temporarily suspended/ ); // Check that the buttons are rendered as expected. - getByText( 'View full deposits history' ); + getByText( 'View full payout history' ); // This one is not rendered when deposits are blocked. expect( queryByText( 'Change deposit schedule' ) ).toBeFalsy(); } ); @@ -386,7 +395,7 @@ describe( 'Deposits Overview information', () => { expect( queryByText( - 'deposit will include funds from your WooCommerce Capital loan', + 'payout will include funds from your WooCommerce Capital loan', { exact: false, ignore: '.a11y-speak-region', @@ -415,7 +424,7 @@ describe( 'Deposits Overview information', () => { } ); const { queryByText } = render( ); - expect( queryByText( /Your first deposit is held for/ ) ).toBeFalsy(); + expect( queryByText( /Your first payout is held for/ ) ).toBeFalsy(); } ); test( 'Confirm new account waiting period notice shows if within waiting period', () => { @@ -433,12 +442,12 @@ describe( 'Deposits Overview information', () => { } ); const { getByText, getByRole } = render( ); - getByText( /Your first deposit is held for/, { + getByText( /Your first payout is held for/, { ignore: '.a11y-speak-region', } ); expect( getByRole( 'link', { name: /Why\?/ } ) ).toHaveAttribute( 'href', - 'https://woocommerce.com/document/woopayments/deposits/deposit-schedule/#new-accounts' + 'https://woocommerce.com/document/woopayments/payouts/payout-schedule/#new-accounts' ); } ); } ); @@ -565,7 +574,7 @@ describe( 'DepositFailureNotice Renders', () => { const { queryByText } = render( ); expect( queryByText( - /Deposits are currently paused because a recent deposit failed./, + /Payouts are currently paused because a recent payout failed./, { ignore: '.a11y-speak-region', } @@ -604,7 +613,7 @@ describe( 'DepositFailureNotice Renders', () => { const { queryByText } = render( ); expect( queryByText( - /Deposits are currently paused because a recent deposit failed./, + /Payouts are currently paused because a recent payout failed./, { ignore: '.a11y-speak-region', } @@ -643,7 +652,7 @@ describe( 'DepositFailureNotice Renders', () => { const { queryByText } = render( ); expect( queryByText( - /Deposits are currently paused because a recent deposit failed./, + /Payouts are currently paused because a recent payout failed./, { ignore: '.a11y-speak-region', } @@ -668,7 +677,7 @@ describe( 'Paused Deposit notice Renders', () => { } ); const { getByText } = render( ); - getByText( /Deposits may be interrupted/, { + getByText( /Payouts may be interrupted/, { ignore: '.a11y-speak-region', } ); } ); @@ -682,7 +691,7 @@ describe( 'Paused Deposit notice Renders', () => { mockDepositOverviews( [ accountOverview ] ); const { queryByText } = render( ); - expect( queryByText( /Deposits may be interrupted/ ) ).toBeFalsy(); + expect( queryByText( /Payouts may be interrupted/ ) ).toBeFalsy(); } ); test( 'When available balance is negative', () => { const accountOverview = createMockNewAccountOverview( @@ -694,7 +703,7 @@ describe( 'Paused Deposit notice Renders', () => { mockDepositOverviews( [ accountOverview ] ); const { queryByText } = render( ); - expect( queryByText( /Deposits may be interrupted/ ) ).toBeFalsy(); + expect( queryByText( /Payouts may be interrupted/ ) ).toBeFalsy(); } ); } ); @@ -723,7 +732,7 @@ describe( 'Minimum Deposit Amount Notice', () => { const { getByText } = render( ); getByText( - /Deposits are paused while your available funds balance remains below €5.00/, + /Payouts are paused while your available funds balance remains below €5.00/, { ignore: '.a11y-speak-region', } @@ -743,7 +752,7 @@ describe( 'Minimum Deposit Amount Notice', () => { const { queryByText } = render( ); expect( queryByText( - /Deposits are paused while your available funds balance remains below/ + /Payouts are paused while your available funds balance remains below/ ) ).toBeFalsy(); } ); diff --git a/client/components/deposits-status/index.tsx b/client/components/deposits-status/index.tsx index b5c61b2cf1c..6e562296322 100644 --- a/client/components/deposits-status/index.tsx +++ b/client/components/deposits-status/index.tsx @@ -63,7 +63,7 @@ const DepositsStatusSuspended: React.FC< DepositsStatusProps > = ( props ) => { const { iconSize } = props; const learnMoreHref = - 'https://woocommerce.com/document/woopayments/deposits/why-deposits-suspended/'; + 'https://woocommerce.com/document/woopayments/payouts/why-payouts-suspended/'; const description = createInterpolateElement( /* translators: - suspended accounts FAQ URL */ diff --git a/client/components/deposits-status/test/__snapshots__/index.js.snap b/client/components/deposits-status/test/__snapshots__/index.js.snap index 9d92c7cd823..b0813fd50e2 100644 --- a/client/components/deposits-status/test/__snapshots__/index.js.snap +++ b/client/components/deposits-status/test/__snapshots__/index.js.snap @@ -20,7 +20,7 @@ exports[`DepositsStatus renders blocked status 1`] = ` Temporarily suspended ( @@ -51,7 +51,7 @@ exports[`DepositsStatus renders blocked status 2`] = ` Temporarily suspended ( @@ -174,7 +174,7 @@ exports[`DepositsStatus renders pending verification status 1`] = ` Temporarily suspended ( diff --git a/client/components/details-link/index.tsx b/client/components/details-link/index.tsx index 03226a5eb8e..0675a6f3e82 100644 --- a/client/components/details-link/index.tsx +++ b/client/components/details-link/index.tsx @@ -15,7 +15,7 @@ import { getAdminUrl } from 'wcpay/utils'; /** * The parent segment is the first part of the URL after the /payments/ path. */ -type ParentSegment = 'deposits' | 'transactions'; +type ParentSegment = 'payouts' | 'transactions'; export const getDetailsURL = ( /** diff --git a/client/components/details-link/test/__snapshots__/index.test.tsx.snap b/client/components/details-link/test/__snapshots__/index.test.tsx.snap index a2b861aebf1..6ea9065b623 100644 --- a/client/components/details-link/test/__snapshots__/index.test.tsx.snap +++ b/client/components/details-link/test/__snapshots__/index.test.tsx.snap @@ -6,7 +6,7 @@ exports[`Details link renders dispute details with ID 1`] = `
{ test( 'renders dispute details with ID', () => { const { container: link } = render( - + ); expect( link ).toMatchSnapshot(); } ); test( 'empty render with no ID', () => { const { container: link } = render( - + ); expect( link ).toMatchSnapshot(); } ); diff --git a/client/components/disputed-order-notice/index.js b/client/components/disputed-order-notice/index.js index de5b720715a..ab51a52d16e 100644 --- a/client/components/disputed-order-notice/index.js +++ b/client/components/disputed-order-notice/index.js @@ -8,7 +8,7 @@ import { createInterpolateElement } from '@wordpress/element'; * Internal dependencies */ import InlineNotice from 'wcpay/components/inline-notice'; -import { formatExplicitCurrency } from 'utils/currency'; +import { formatExplicitCurrency } from 'multi-currency/interface/functions'; import { reasons } from 'wcpay/disputes/strings'; import { getDetailsURL } from 'wcpay/components/details-link'; import { diff --git a/client/components/disputed-order-notice/test/__snapshots__/index.test.js.snap b/client/components/disputed-order-notice/test/__snapshots__/index.test.js.snap new file mode 100644 index 00000000000..4c3f5a3611a --- /dev/null +++ b/client/components/disputed-order-notice/test/__snapshots__/index.test.js.snap @@ -0,0 +1,91 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`DisputedOrderNoticeHandler renders regular dispute notice 1`] = ` +
+
+
+
+
+ + This order has a payment dispute for $10.00 for the reason 'Transaction unauthorized'. + + + Please respond before Oct 28, 2023. +
+ +
+
+
+
+
+
+
+`; + +exports[`DisputedOrderNoticeHandler renders urgent dispute notice 1`] = ` +
+
+
+
+
+ + Please resolve the dispute on this order of $10.00 labeled 'Transaction unauthorized' by Oct 28, 2023. + + + (Last day today) +
+ +
+
+
+
+
+
+
+`; diff --git a/client/components/disputed-order-notice/test/index.test.js b/client/components/disputed-order-notice/test/index.test.js new file mode 100644 index 00000000000..7e44da132e0 --- /dev/null +++ b/client/components/disputed-order-notice/test/index.test.js @@ -0,0 +1,111 @@ +/** + * External dependencies + */ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +/** + * Internal dependencies + */ +import DisputedOrderNoticeHandler from '../index'; +import { useCharge } from 'wcpay/data'; + +jest.mock( 'wcpay/data', () => ( { + useCharge: jest.fn(), +} ) ); + +jest.mock( 'tracks', () => ( { + recordEvent: jest.fn(), +} ) ); + +describe( 'DisputedOrderNoticeHandler', () => { + const mockCharge = { + dispute: { + status: 'needs_response', + reason: 'fraudulent', + amount: 1000, + currency: 'USD', + evidence_details: { + due_by: 1698500219, + }, + }, + }; + + beforeEach( () => { + window.wcpaySettings = { + zeroDecimalCurrencies: [], + connect: { + country: 'US', + }, + }; + useCharge.mockReturnValue( { data: mockCharge } ); + } ); + + afterEach( () => { + jest.useRealTimers(); + jest.clearAllMocks(); + } ); + + test( 'renders urgent dispute notice', () => { + const fixedDate = new Date( '2023-10-28T00:00:00Z' ); + jest.useFakeTimers(); + jest.setSystemTime( fixedDate ); + + const { container } = render( + + ); + const disputeMessages = screen.getAllByText( + /Please resolve the dispute on this order of/ + ); + expect( disputeMessages[ 0 ] ).toBeInTheDocument(); + expect( screen.getByRole( 'button' ) ).toHaveTextContent( + 'Respond today' + ); + expect( container ).toMatchSnapshot(); + } ); + + test( 'renders regular dispute notice', () => { + const fixedDate = new Date( '2023-10-20T00:00:00Z' ); + jest.useFakeTimers(); + jest.setSystemTime( fixedDate ); + + const { container } = render( + + ); + const disputeMessages = screen.getAllByText( /Please respond before/ ); + expect( disputeMessages[ 0 ] ).toBeInTheDocument(); + expect( screen.getByRole( 'button' ) ).toHaveTextContent( + 'Respond now' + ); + expect( container ).toMatchSnapshot(); + } ); + + test( 'does not render notice if no dispute', () => { + useCharge.mockReturnValue( { data: {} } ); + const { container } = render( + + ); + expect( container ).toBeEmptyDOMElement(); + } ); + + test( 'does not render notice if dispute is not awaiting response', () => { + mockCharge.dispute.status = 'won'; + render( + + ); + expect( + screen.queryByText( /Please resolve the dispute on this order of/ ) + ).not.toBeInTheDocument(); + } ); +} ); diff --git a/client/components/payment-activity/payment-data-tile.tsx b/client/components/payment-activity/payment-data-tile.tsx index f9bbfbf7318..7c0d190d79f 100644 --- a/client/components/payment-activity/payment-data-tile.tsx +++ b/client/components/payment-activity/payment-data-tile.tsx @@ -9,7 +9,7 @@ import { recordEvent } from 'wcpay/tracks'; /** * Internal dependencies */ -import { formatCurrency } from 'wcpay/utils/currency'; +import { formatCurrency } from 'multi-currency/interface/functions'; import Loadable from '../loadable'; import './style.scss'; diff --git a/client/components/sandbox-mode-switch-to-live-notice/modal/index.tsx b/client/components/sandbox-mode-switch-to-live-notice/modal/index.tsx index eaa7dcef0aa..43278a178d0 100644 --- a/client/components/sandbox-mode-switch-to-live-notice/modal/index.tsx +++ b/client/components/sandbox-mode-switch-to-live-notice/modal/index.tsx @@ -82,7 +82,7 @@ const SetupLivePaymentsModal: React.FC< Props > = ( { ) } { __( - 'We will need your banking details in order to process any deposits to you.', + 'We will need your banking details in order to process any payouts to you.', 'woocommerce-payments' ) }
diff --git a/client/components/test-mode-notice/index.tsx b/client/components/test-mode-notice/index.tsx index 6f13da9def2..7b8ac27073d 100644 --- a/client/components/test-mode-notice/index.tsx +++ b/client/components/test-mode-notice/index.tsx @@ -31,7 +31,7 @@ interface Props { const nounToUse = { documents: __( 'document', 'woocommerce-payments' ), - deposits: __( 'deposit', 'woocommerce-payments' ), + deposits: __( 'payout', 'woocommerce-payments' ), disputes: __( 'dispute', 'woocommerce-payments' ), loans: __( 'loan', 'woocommerce-payments' ), payments: __( 'order', 'woocommerce-payments' ), @@ -143,7 +143,9 @@ const getNoticeContent = ( 'Viewing test %1$s. To view live %1s, disable test mode in {{settingsLink}}%2s settings{{/settingsLink}}.', 'woocommerce-payments' ), - currentPage, + 'deposits' === currentPage + ? 'payouts' + : currentPage, 'WooPayments' ), components: { diff --git a/client/components/test-mode-notice/test/__snapshots__/index.tsx.snap b/client/components/test-mode-notice/test/__snapshots__/index.tsx.snap index d3f06d3f8bb..92877be2b29 100644 --- a/client/components/test-mode-notice/test/__snapshots__/index.tsx.snap +++ b/client/components/test-mode-notice/test/__snapshots__/index.tsx.snap @@ -22,7 +22,7 @@ exports[`Test mode notification Returns valid component for deposits page 1`] =
- Viewing test deposits. To view live deposits, disable test mode in + Viewing test payouts. To view live payouts, disable test mode in diff --git a/client/components/welcome/currency-select.tsx b/client/components/welcome/currency-select.tsx index 7f82c412313..32c1e5a3cd9 100644 --- a/client/components/welcome/currency-select.tsx +++ b/client/components/welcome/currency-select.tsx @@ -8,7 +8,7 @@ import { decodeEntities } from '@wordpress/html-entities'; * Internal dependencies */ import { useSelectedCurrency } from 'overview/hooks'; -import { getCurrency } from 'utils/currency'; +import { getCurrency } from 'multi-currency/interface/functions'; import InlineLabelSelect from '../inline-label-select'; import { recordEvent } from 'tracks'; diff --git a/client/connect-account-page/strings.tsx b/client/connect-account-page/strings.tsx index 808b9c13705..95c1be5a59d 100644 --- a/client/connect-account-page/strings.tsx +++ b/client/connect-account-page/strings.tsx @@ -37,7 +37,7 @@ export default { ), paymentMethods: { deposits: { - title: __( 'Deposits', 'woocommerce-payments' ), + title: __( 'Payouts', 'woocommerce-payments' ), value: __( 'Automatic - Daily', 'woocommerce-payments' ), }, capture: { @@ -58,7 +58,7 @@ export default { 'woocommerce-payments' ), usp3: __( - 'Earn recurring revenue and get deposits into your bank account.', + 'Earn recurring revenue and get payouts into your bank account.', 'woocommerce-payments' ), sandboxMode: { @@ -111,7 +111,7 @@ export default { 'woocommerce-payments' ), }, - button: __( 'enable deposits.', 'woocommerce-payments' ), + button: __( 'enable payouts.', 'woocommerce-payments' ), }, infoModal: { title: sprintf( @@ -252,7 +252,7 @@ export default { step2: { heading: __( 'Provide a few business details', 'woocommerce-payments' ), description: __( - 'Next we’ll ask you to verify your business and payment details to enable deposits.', + 'Next we’ll ask you to verify your business and payment details to enable payouts.', 'woocommerce-payments' ), }, diff --git a/client/connect-account-page/test/__snapshots__/index.test.tsx.snap b/client/connect-account-page/test/__snapshots__/index.test.tsx.snap index 256570bcc8c..3cfc2216716 100644 --- a/client/connect-account-page/test/__snapshots__/index.test.tsx.snap +++ b/client/connect-account-page/test/__snapshots__/index.test.tsx.snap @@ -50,7 +50,7 @@ exports[`ConnectAccountPage should render correctly 1`] = ` class="components-button is-link" type="button" > - enable deposits. + enable payouts.
@@ -133,7 +133,7 @@ exports[`ConnectAccountPage should render correctly 1`] = ` >

- Deposits + Payouts

Automatic - Daily @@ -315,7 +315,7 @@ exports[`ConnectAccountPage should render correctly with WooPay eligible 1`] = ` class="components-button is-link" type="button" > - enable deposits. + enable payouts.
@@ -398,7 +398,7 @@ exports[`ConnectAccountPage should render correctly with WooPay eligible 1`] = ` >

- Deposits + Payouts

Automatic - Daily @@ -542,7 +542,7 @@ exports[`ConnectAccountPage should render correctly with an incentive 1`] = ` class="components-button is-link" type="button" > - enable deposits. + enable payouts.
@@ -625,7 +625,7 @@ exports[`ConnectAccountPage should render correctly with an incentive 1`] = ` >

- Deposits + Payouts

Automatic - Daily diff --git a/client/connect-account-page/test/info-notice-modal.test.tsx b/client/connect-account-page/test/info-notice-modal.test.tsx index 0b24620aa81..207935034dc 100644 --- a/client/connect-account-page/test/info-notice-modal.test.tsx +++ b/client/connect-account-page/test/info-notice-modal.test.tsx @@ -27,7 +27,7 @@ describe( 'Connect Account Page – Info Notice Modal', () => { render( ); const enableDeposits = screen.getByRole( 'button', { - name: /enable deposits./i, + name: /enable payouts./i, } ); userEvent.click( enableDeposits ); diff --git a/client/data/deposits/actions.js b/client/data/deposits/actions.js index 392b890657c..d4063e3e0a8 100644 --- a/client/data/deposits/actions.js +++ b/client/data/deposits/actions.js @@ -6,7 +6,7 @@ import { apiFetch } from '@wordpress/data-controls'; import { dispatch } from '@wordpress/data'; import { __, sprintf } from '@wordpress/i18n'; -import { formatCurrency } from 'utils/currency'; +import { formatCurrency } from 'multi-currency/interface/functions'; /** * Internal Dependencies @@ -112,7 +112,7 @@ export function* submitInstantDeposit( currency ) { yield dispatch( 'core/notices' ).createSuccessNotice( sprintf( __( - 'Instant deposit for %s in transit.', + 'Instant payout for %s in transit.', 'woocommerce-payments' ), formatCurrency( deposit.amount ) @@ -123,7 +123,7 @@ export function* submitInstantDeposit( currency ) { label: __( 'View details', 'woocommerce-payments' ), url: getAdminUrl( { page: 'wc-admin', - path: '/payments/deposits/details', + path: '/payments/payouts/details', id: deposit.id, } ), }, @@ -132,7 +132,7 @@ export function* submitInstantDeposit( currency ) { ); } catch { yield dispatch( 'core/notices' ).createErrorNotice( - __( 'Error creating instant deposit.', 'woocommerce-payments' ) + __( 'Error creating instant payout.', 'woocommerce-payments' ) ); } finally { yield dispatch( STORE_NAME ).finishResolution( 'getInstantDeposit', [ diff --git a/client/data/deposits/resolvers.js b/client/data/deposits/resolvers.js index 52961f25570..a4a0ad14e26 100644 --- a/client/data/deposits/resolvers.js +++ b/client/data/deposits/resolvers.js @@ -45,7 +45,7 @@ export function* getDeposit( id ) { yield controls.dispatch( 'core/notices', 'createErrorNotice', - __( 'Error retrieving deposit.', 'woocommerce-payments' ) + __( 'Error retrieving payout.', 'woocommerce-payments' ) ); } } @@ -64,7 +64,7 @@ export function* getAllDepositsOverviews() { 'core/notices', 'createErrorNotice', __( - "Error retrieving all deposits' overviews.", + "Error retrieving all payouts' overviews.", 'woocommerce-payments' ) ); @@ -129,7 +129,7 @@ export function* getDeposits( query ) { yield controls.dispatch( 'core/notices', 'createErrorNotice', - __( 'Error retrieving deposits.', 'woocommerce-payments' ) + __( 'Error retrieving payouts.', 'woocommerce-payments' ) ); yield updateErrorForDepositQuery( query, null, e ); } diff --git a/client/data/index.ts b/client/data/index.ts index d20938feb56..878ecdc11f6 100644 --- a/client/data/index.ts +++ b/client/data/index.ts @@ -18,7 +18,6 @@ export * from './charges/hooks'; export * from './timeline/hooks'; export * from './disputes/hooks'; export * from './settings/hooks'; -export * from './multi-currency'; export * from './card-readers/hooks'; export * from './capital/hooks'; export * from './documents/hooks'; diff --git a/client/data/multi-currency/index.js b/client/data/multi-currency/index.js deleted file mode 100644 index c524cca8b05..00000000000 --- a/client/data/multi-currency/index.js +++ /dev/null @@ -1,12 +0,0 @@ -/** @format */ - -/** - * Internal dependencies - */ -import reducer from './reducer'; -import * as selectors from './selectors'; -import * as actions from './actions'; -import * as resolvers from './resolvers'; - -export { reducer, selectors, actions, resolvers }; -export * from './hooks'; diff --git a/client/data/store.js b/client/data/store.js index 974efdb1e07..c4387901c37 100644 --- a/client/data/store.js +++ b/client/data/store.js @@ -14,7 +14,6 @@ import * as charges from './charges'; import * as timeline from './timeline'; import * as disputes from './disputes'; import * as settings from './settings'; -import * as multiCurrency from './multi-currency'; import * as readers from './card-readers'; import * as capital from './capital'; import * as documents from './documents'; @@ -33,7 +32,6 @@ export const initStore = () => timeline: timeline.reducer, disputes: disputes.reducer, settings: settings.reducer, - multiCurrency: multiCurrency.reducer, readers: readers.reducer, capital: capital.reducer, documents: documents.reducer, @@ -49,7 +47,6 @@ export const initStore = () => ...timeline.actions, ...disputes.actions, ...settings.actions, - ...multiCurrency.actions, ...readers.actions, ...capital.actions, ...documents.actions, @@ -66,7 +63,6 @@ export const initStore = () => ...timeline.selectors, ...disputes.selectors, ...settings.selectors, - ...multiCurrency.selectors, ...readers.selectors, ...capital.selectors, ...documents.selectors, @@ -82,7 +78,6 @@ export const initStore = () => ...timeline.resolvers, ...disputes.resolvers, ...settings.resolvers, - ...multiCurrency.resolvers, ...readers.resolvers, ...capital.resolvers, ...documents.resolvers, diff --git a/client/deposits/details/index.tsx b/client/deposits/details/index.tsx index 4d47ae51d6a..2176b079377 100644 --- a/client/deposits/details/index.tsx +++ b/client/deposits/details/index.tsx @@ -34,16 +34,37 @@ import Page from 'components/page'; import ErrorBoundary from 'components/error-boundary'; import { TestModeNotice } from 'components/test-mode-notice'; import InlineNotice from 'components/inline-notice'; -import { formatCurrency, formatExplicitCurrency } from 'utils/currency'; -import { displayStatus } from '../strings'; +import { + formatCurrency, + formatExplicitCurrency, +} from 'multi-currency/interface/functions'; +import { depositStatusLabels } from '../strings'; import './style.scss'; +import { PayoutsRenameNotice } from '../rename-notice'; /** * Renders the deposit status indicator UI, re-purposing the OrderStatus component from @woocommerce/components. */ -const Status: React.FC< { status: string } > = ( { status } ) => ( - -); +const DepositStatusIndicator: React.FC< { + deposit: Pick< CachedDeposit, 'status' | 'type' >; +} > = ( { deposit } ) => { + let displayStatusMap = depositStatusLabels; + + // Withdrawals are displayed as 'Deducted' instead of 'Paid' when the status is 'paid'. + if ( deposit.type === 'withdrawal' ) { + displayStatusMap = { + ...displayStatusMap, + paid: displayStatusMap.deducted, + }; + } + + return ( + + ); +}; interface SummaryItemProps { label: string; @@ -99,9 +120,15 @@ export const DepositOverview: React.FC< DepositOverviewProps > = ( { ); } - const depositDateLabel = deposit.automatic - ? __( 'Deposit date', 'woocommerce-payments' ) - : __( 'Instant deposit date', 'woocommerce-payments' ); + const isWithdrawal = deposit.type === 'withdrawal'; + + let depositDateLabel = __( 'Payout date', 'woocommerce-payments' ); + if ( ! deposit.automatic ) { + depositDateLabel = __( 'Instant payout date', 'woocommerce-payments' ); + } + if ( isWithdrawal ) { + depositDateLabel = __( 'Withdrawal date', 'woocommerce-payments' ); + } const depositDateItem = ( = ( { true // TODO Change call to gmdateI18n and remove this deprecated param once WP 5.4 support ends. ) } - value={ } + value={ } detail={ deposit.bankAccount } /> ); @@ -135,16 +162,30 @@ export const DepositOverview: React.FC< DepositOverviewProps > = ( { ) : ( { () => [ depositDateItem, = ( { />, = ( { return ( + { isLoading ? ( @@ -217,7 +266,7 @@ export const DepositDetails: React.FC< DepositDetailsProps > = ( { { __( - 'Deposit transactions', + 'Payout transactions', 'woocommerce-payments' ) } @@ -226,12 +275,12 @@ export const DepositDetails: React.FC< DepositDetailsProps > = ( { { interpolateComponents( { /* Translators: {{learnMoreLink}} is a link element (
). */ mixedString: __( - `We're unable to show transaction history on instant deposits. {{learnMoreLink}}Learn more{{/learnMoreLink}}`, + `We're unable to show transaction history on instant payouts. {{learnMoreLink}}Learn more{{/learnMoreLink}}`, 'woocommerce-payments' ), components: { learnMoreLink: ( - + ), }, } ) } diff --git a/client/deposits/details/style.scss b/client/deposits/details/style.scss index b05e381fde0..0031184d4cf 100644 --- a/client/deposits/details/style.scss +++ b/client/deposits/details/style.scss @@ -1,24 +1,30 @@ .wcpay-deposit-overview { .woocommerce-order-status { margin-bottom: 4px; + white-space: nowrap; } .woocommerce-order-status__indicator { width: 0.85em; height: 0.85em; + // is-canceled uses the default gray color. + &.is-paid { - background: $studio-green-50; - border-color: $studio-green-5; + background: $wp-green-30; + border-color: $wp-green-5; + } + &.is-pending { + background: $wp-yellow-20; + border-color: $wp-yellow-5; } - &.is-pending, &.is-in_transit { - background: $studio-yellow-30; - border-color: $studio-yellow-5; + background: $wp-blue-30; + border-color: $wp-blue-5; } &.is-failed { - background: $studio-red-50; - border-color: $studio-red-5; + background: $wp-red-50; + border-color: $wp-red-10; } } @@ -34,11 +40,11 @@ } .wcpay-deposit-fee { - color: $studio-red-50; + color: $wp-red-70; } .wcpay-deposit-net { - color: $studio-green-30; + color: $wp-green-70; } .wcpay-deposit-automatic ul { diff --git a/client/deposits/details/test/__snapshots__/index.tsx.snap b/client/deposits/details/test/__snapshots__/index.tsx.snap index f3c47816895..fecce68ae08 100644 --- a/client/deposits/details/test/__snapshots__/index.tsx.snap +++ b/client/deposits/details/test/__snapshots__/index.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Deposit overview renders automatic deposit correctly 1`] = ` +exports[`Deposit overview renders automatic payout correctly 1`] = `
- Deposit date: Jan 2, 2020 + Payout date: Jan 2, 2020
- Paid + Completed (paid)
@@ -72,6 +72,78 @@ exports[`Deposit overview renders automatic deposit correctly 1`] = `
`; +exports[`Deposit overview renders automatic withdrawal correctly 1`] = ` +
+
+
+
+
    +
  • +
    +
    + Withdrawal date: Jan 2, 2020 +
    +
    +
    +
    + + Completed (deducted) +
    +
    +
    +
    + MOCK BANK •••• 1234 (USD) +
    +
    +
  • +
  • + -$20.00 +
  • +
+
+ +
+`; + exports[`Deposit overview renders instant deposit correctly 1`] = `
@@ -101,7 +173,7 @@ exports[`Deposit overview renders instant deposit correctly 1`] = `
- Instant deposit date: Jan 2, 2020 + Instant payout date: Jan 2, 2020
- Paid + Completed (paid)
@@ -135,7 +207,7 @@ exports[`Deposit overview renders instant deposit correctly 1`] = `
- Deposit amount + Payout amount
- Net deposit amount + Net payout amount
{ }; } ); - test( 'renders automatic deposit correctly', () => { - const { container: overview } = render( + test( 'renders automatic payout correctly', () => { + const { container: overview, getByText } = render( ); + getByText( /Payout date:/ ); + getByText( 'Completed (paid)' ); + expect( overview ).toMatchSnapshot(); + } ); + + test( 'renders automatic withdrawal correctly', () => { + const { container: overview, getByText } = render( + + ); + getByText( /Withdrawal date:/ ); + getByText( 'Completed (deducted)' ); expect( overview ).toMatchSnapshot(); } ); diff --git a/client/deposits/filters/config.js b/client/deposits/filters/config.js index c63435bcaca..ee5b198e7d5 100644 --- a/client/deposits/filters/config.js +++ b/client/deposits/filters/config.js @@ -7,15 +7,24 @@ import { getSetting } from '@woocommerce/settings'; /** * Internal dependencies */ -import { displayStatus } from 'deposits/strings'; +import { depositStatusLabels } from 'deposits/strings'; -const depositStatusOptions = Object.entries( - displayStatus -).map( ( [ status, label ] ) => ( { label, value: status } ) ); +const depositStatusOptions = Object.entries( depositStatusLabels ) + // Ignore the 'deducted' status, which is only a display status and not to be used in filters. + .filter( ( [ status ] ) => status !== 'deducted' ) + .map( ( [ status, label ] ) => { + if ( status === 'paid' ) { + return { + label: __( 'Completed', 'woocommerce-payments' ), + value: 'paid', + }; + } + return { label, value: status }; + } ); export const filters = [ { - label: __( 'Deposit currency', 'woocommerce-payments' ), + label: __( 'Payout currency', 'woocommerce-payments' ), param: 'store_currency_is', staticParams: [ 'paged', @@ -53,7 +62,7 @@ export const filters = [ showFilters: () => true, filters: [ { - label: __( 'All deposits', 'woocommerce-payments' ), + label: __( 'All payouts', 'woocommerce-payments' ), value: 'all', }, { @@ -74,21 +83,18 @@ export const advancedFilters = { /** translators: A sentence describing filters for deposits. See screen shot for context: https://d.pr/i/NcGpwL */ title: wooCommerceVersion < 7.8 - ? __( - 'Deposits match {{select /}} filters', - 'woocommerce-payments' - ) - : __( 'Deposits match filters', 'woocommerce-payments' ), filters: { date: { labels: { add: __( 'Date', 'woocommerce-payments' ), remove: __( - 'Remove deposit date filter', + 'Remove payout date filter', 'woocommerce-payments' ), rule: __( - 'Select a deposit date filter match', + 'Select a payout date filter match', 'woocommerce-payments' ), /* translators: A sentence describing a deposit date filter. See screen shot for context: https://d.pr/i/NcGpwL */ @@ -102,7 +108,7 @@ export const advancedFilters = { 'Date ', 'woocommerce-payments' ), - filter: __( 'Select a deposit date', 'woocommerce-payments' ), + filter: __( 'Select a payout date', 'woocommerce-payments' ), }, rules: [ { @@ -126,11 +132,11 @@ export const advancedFilters = { labels: { add: __( 'Status', 'woocommerce-payments' ), remove: __( - 'Remove deposit status filter', + 'Remove payout status filter', 'woocommerce-payments' ), rule: __( - 'Select a deposit status filter match', + 'Select a payout status filter match', 'woocommerce-payments' ), /* translators: A sentence describing a deposit status filter. See screen shot for context: https://d.pr/i/NcGpwL */ @@ -144,20 +150,20 @@ export const advancedFilters = { 'Status ', 'woocommerce-payments' ), - filter: __( 'Select a deposit status', 'woocommerce-payments' ), + filter: __( 'Select a payout status', 'woocommerce-payments' ), }, rules: [ { value: 'is', /* translators: Sentence fragment, logical, "Is" refers to searching for deposits matching a chosen deposit status. Screenshot for context: https://d.pr/i/NcGpwL */ - label: _x( 'Is', 'deposit status', 'woocommerce-payments' ), + label: _x( 'Is', 'payout status', 'woocommerce-payments' ), }, { value: 'is_not', /* translators: Sentence fragment, logical, "Is not" refers to searching for deposits that don\'t match a chosen deposit status. Screenshot for context: https://d.pr/i/NcGpwL */ label: _x( 'Is not', - 'deposit status', + 'payout status', 'woocommerce-payments' ), }, diff --git a/client/deposits/filters/index.js b/client/deposits/filters/index.js index 34cc4bbdf52..1393109a06e 100644 --- a/client/deposits/filters/index.js +++ b/client/deposits/filters/index.js @@ -8,7 +8,7 @@ import { getQuery } from '@woocommerce/navigation'; * Internal dependencies */ import { filters, advancedFilters } from './config'; -import { formatCurrencyName } from '../../utils/currency'; +import { formatCurrencyName } from 'multi-currency/interface/functions'; export const DepositsFilters = ( props ) => { const populateDepositCurrencies = ( filtersConfiguration ) => { @@ -38,7 +38,7 @@ export const DepositsFilters = ( props ) => { filters={ populateDepositCurrencies( filters ) } advancedFilters={ advancedFilters } showDatePicker={ false } - path="/payments/deposits" + path="/payments/payouts" query={ getQuery() } />
diff --git a/client/deposits/filters/test/__snapshots__/index.js.snap b/client/deposits/filters/test/__snapshots__/index.js.snap index 5f02b248a6c..962eccde043 100644 --- a/client/deposits/filters/test/__snapshots__/index.js.snap +++ b/client/deposits/filters/test/__snapshots__/index.js.snap @@ -5,7 +5,7 @@ HTMLOptionsCollection [ ,
: instant payout doc URL */ sprintf( __( - 'Need cash in a hurry? Instant deposits are available within 30 minutes for a nominal %s service fee. Learn more', + 'Need cash in a hurry? Instant payouts are available within 30 minutes for a nominal %s service fee. Learn more', 'woocommerce-payments' ), feePercentage @@ -54,20 +57,20 @@ const InstantDepositModal: React.FC< InstantDepositModalProps > = ( { return (

{ description }

    -
  • +
  • { __( - 'Balance available for instant deposit: ', + 'Balance available for instant payout: ', 'woocommerce-payments' ) } { formatCurrency( amount ) }
  • -
  • +
  • { sprintf( /* translators: %s - amount representing the fee percentage */ __( '%s service fee: ', 'woocommerce-payments' ), @@ -75,13 +78,13 @@ const InstantDepositModal: React.FC< InstantDepositModalProps > = ( { ) } -{ formatCurrency( fee ) }
  • -
  • - { __( 'Net deposit amount: ', 'woocommerce-payments' ) } +
  • + { __( 'Net payout amount: ', 'woocommerce-payments' ) } { formatExplicitCurrency( net ) }
-
+
@@ -92,8 +95,8 @@ const InstantDepositModal: React.FC< InstantDepositModalProps > = ( { disabled={ inProgress } > { sprintf( - /* translators: %s: Monetary amount to deposit */ - __( 'Deposit %s now', 'woocommerce-payments' ), + /* translators: %s: Monetary amount to pay out */ + __( 'Pay out %s now', 'woocommerce-payments' ), formatExplicitCurrency( net ) ) } @@ -102,4 +105,4 @@ const InstantDepositModal: React.FC< InstantDepositModalProps > = ( { ); }; -export default InstantDepositModal; +export default InstantPayoutModal; diff --git a/client/deposits/instant-deposits/style.scss b/client/deposits/instant-payouts/style.scss similarity index 74% rename from client/deposits/instant-deposits/style.scss rename to client/deposits/instant-payouts/style.scss index 8232fd2508b..b3c16187b5f 100644 --- a/client/deposits/instant-deposits/style.scss +++ b/client/deposits/instant-payouts/style.scss @@ -1,4 +1,4 @@ -div.wcpay-instant-deposits-modal { +div.wcpay-instant-payout-modal { max-width: 500px; p { @@ -20,17 +20,17 @@ div.wcpay-instant-deposits-modal { } } - .wcpay-instant-deposits-modal__balance { + .wcpay-instant-payout-modal__balance { padding-bottom: 0; } - .wcpay-instant-deposits-modal__fee { + .wcpay-instant-payout-modal__fee { span { color: $studio-red-50; } } - .wcpay-instant-deposits-modal__net { + .wcpay-instant-payout-modal__net { border-top: 1px solid $studio-gray-5; span { diff --git a/client/deposits/instant-deposits/test/__snapshots__/index.tsx.snap b/client/deposits/instant-payouts/test/__snapshots__/index.tsx.snap similarity index 70% rename from client/deposits/instant-deposits/test/__snapshots__/index.tsx.snap rename to client/deposits/instant-payouts/test/__snapshots__/index.tsx.snap index 2eec0aa2041..aca4e115afd 100644 --- a/client/deposits/instant-deposits/test/__snapshots__/index.tsx.snap +++ b/client/deposits/instant-payouts/test/__snapshots__/index.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Instant deposit button and modal button renders correctly with balance 1`] = ` +exports[`Instant payout button and modal button renders correctly with balance 1`] = `

- Need cash in a hurry? Instant deposits are available within 30 minutes for a nominal 1.5% service fee. + Need cash in a hurry? Instant payouts are available within 30 minutes for a nominal 1.5% service fee. @@ -66,15 +66,15 @@ exports[`Instant deposit button and modal modal renders correctly 1`] = `

  • - Balance available for instant deposit: + Balance available for instant payout: $123.45
  • 1.5% service fee: @@ -83,16 +83,16 @@ exports[`Instant deposit button and modal modal renders correctly 1`] = `
  • - Net deposit amount: + Net payout amount: $122.22
diff --git a/client/deposits/instant-deposits/test/index.tsx b/client/deposits/instant-payouts/test/index.tsx similarity index 90% rename from client/deposits/instant-deposits/test/index.tsx rename to client/deposits/instant-payouts/test/index.tsx index d8b2d8ec8e6..4af2ee92233 100644 --- a/client/deposits/instant-deposits/test/index.tsx +++ b/client/deposits/instant-payouts/test/index.tsx @@ -7,7 +7,7 @@ import { fireEvent, render, screen } from '@testing-library/react'; /** * Internal dependencies */ -import InstantDepositButton from '../'; +import InstantDepositButton from '..'; import { useInstantDeposit } from 'wcpay/data'; import type * as AccountOverview from 'wcpay/types/account-overview'; @@ -41,7 +41,7 @@ declare const global: { }; }; -describe( 'Instant deposit button and modal', () => { +describe( 'Instant payout button and modal', () => { beforeEach( () => { jest.clearAllMocks(); global.wcpaySettings = { @@ -74,7 +74,7 @@ describe( 'Instant deposit button and modal', () => { ); expect( - screen.queryByRole( 'dialog', { name: /instant deposit/i } ) + screen.queryByRole( 'dialog', { name: /instant payout/i } ) ).not.toBeInTheDocument(); fireEvent.click( screen.getByRole( 'button', { @@ -82,7 +82,7 @@ describe( 'Instant deposit button and modal', () => { } ) ); const modal = screen.queryByRole( 'dialog', { - name: /instant deposit/i, + name: /instant payout/i, } ); expect( modal ).toBeInTheDocument(); expect( modal ).toMatchSnapshot(); diff --git a/client/deposits/list/index.tsx b/client/deposits/list/index.tsx index 21c48d2f631..c991e7e7ec3 100644 --- a/client/deposits/list/index.tsx +++ b/client/deposits/list/index.tsx @@ -3,7 +3,6 @@ /** * External dependencies */ -import { DepositsTableHeader } from 'wcpay/types/deposits'; import React, { useState } from 'react'; import { recordEvent } from 'tracks'; import { useMemo } from '@wordpress/element'; @@ -19,14 +18,19 @@ import { } from '@woocommerce/csv-export'; import apiFetch from '@wordpress/api-fetch'; import { useDispatch } from '@wordpress/data'; +import { parseInt } from 'lodash'; /** * Internal dependencies. */ +import type { DepositsTableHeader } from 'wcpay/types/deposits'; import { useDeposits, useDepositsSummary } from 'wcpay/data'; import { useReportingExportLanguage } from 'data/index'; -import { displayType, displayStatus } from '../strings'; -import { formatExplicitCurrency, formatExportAmount } from 'utils/currency'; +import { displayType, depositStatusLabels } from '../strings'; +import { + formatExplicitCurrency, + formatExportAmount, +} from 'multi-currency/interface/functions'; import DetailsLink, { getDetailsURL } from 'components/details-link'; import ClickableCell from 'components/clickable-cell'; import Page from '../../components/page'; @@ -44,7 +48,6 @@ import CSVExportModal from 'components/csv-export-modal'; import { ReportingExportLanguageHook } from 'wcpay/settings/reporting-settings/interfaces'; import './style.scss'; -import { parseInt } from 'lodash'; const getColumns = ( sortByDate?: boolean ): DepositsTableHeader[] => [ { @@ -117,19 +120,19 @@ export const DepositsList = (): JSX.Element => { const rows = deposits.map( ( deposit ) => { const clickable = ( children: React.ReactNode ): JSX.Element => ( recordEvent( 'wcpay_deposits_row_click' ) } > { children } ); const detailsLink = ( - + ); const dateDisplay = ( recordEvent( 'wcpay_deposits_row_click' ) } > { dateI18n( @@ -155,10 +158,8 @@ export const DepositsList = (): JSX.Element => { ), }, status: { - value: displayStatus[ deposit.status ], - display: clickable( - - ), + value: depositStatusLabels[ deposit.status ], + display: clickable( ), }, bankAccount: { value: deposit.bankAccount, @@ -185,8 +186,8 @@ export const DepositsList = (): JSX.Element => { summary = [ { label: _n( - 'deposit', - 'deposits', + 'payout', + 'payouts', depositsSummary.count, 'woocommerce-payments' ), @@ -211,7 +212,7 @@ export const DepositsList = (): JSX.Element => { depositsSummary.store_currencies || ( isCurrencyFiltered ? [ getQuery().store_currency_is ] : [] ); - const title = __( 'Deposits', 'woocommerce-payments' ); + const title = __( 'Payouts', 'woocommerce-payments' ); const downloadable = !! rows.length; @@ -316,7 +317,7 @@ export const DepositsList = (): JSX.Element => { const csvColumns = [ { ...columns[ 0 ], - label: __( 'Deposit Id', 'woocommerce-payments' ), + label: __( 'Payout Id', 'woocommerce-payments' ), }, ...columns.slice( 1 ), ]; @@ -364,7 +365,7 @@ export const DepositsList = (): JSX.Element => { - Deposit currency + Payout currency :
- All deposits + All payouts
@@ -96,7 +96,7 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` data-wp-c16t="true" data-wp-component="Text" > - Deposit history + Payout history
- Deposit history + Payout history @@ -321,7 +321,7 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` > Jan 2, 2020 @@ -354,10 +354,10 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` - Deposit + Payout $20.00 @@ -378,13 +378,13 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` - Paid + Completed (paid) @@ -394,7 +394,7 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` MOCK BANK •••• 1234 (USD) @@ -408,7 +408,7 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` > Jan 3, 2020 @@ -441,7 +441,7 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` Withdrawal @@ -453,7 +453,7 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` $30.00 @@ -465,7 +465,7 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` + MOCK BANK •••• 1234 (USD) + + + + + + + + + + + + + + + + Jan 4, 2020 + + + + + Withdrawal + + + + + $40.00 + + + + + + Completed (deducted) + + + + + MOCK BANK •••• 1234 (USD) @@ -512,7 +599,7 @@ exports[`Deposits list renders correctly a single deposit 1`] = ` - deposit + payout
  • - Deposit currency + Payout currency :
    - All deposits + All payouts
    @@ -645,7 +732,7 @@ exports[`Deposits list renders correctly with multiple currencies 1`] = ` data-wp-c16t="true" data-wp-component="Text" > - Deposit history + Payout history
  • diff --git a/client/deposits/list/test/index.tsx b/client/deposits/list/test/index.tsx index 7c6ea8f9d17..d70561fb6d4 100644 --- a/client/deposits/list/test/index.tsx +++ b/client/deposits/list/test/index.tsx @@ -63,6 +63,15 @@ const mockDeposits = [ bankAccount: 'MOCK BANK •••• 1234 (USD)', currency: 'USD', } as CachedDeposit, + { + id: 'po_mock3', + date: '2020-01-04 17:46:02', + type: 'withdrawal', + amount: 4000, + status: 'paid', + bankAccount: 'MOCK BANK •••• 1234 (USD)', + currency: 'USD', + } as CachedDeposit, ]; declare const global: { @@ -272,7 +281,7 @@ describe( 'Deposits list', () => { getByRole( 'button', { name: 'Download' } ).click(); const expected = [ - '"Deposit Id"', + '"Payout Id"', 'Date', 'Type', 'Amount', @@ -317,7 +326,9 @@ describe( 'Deposits list', () => { csvFirstDeposit[ 3 ] ) ).not.toBe( -1 ); // amount - expect( csvFirstDeposit[ 4 ] ).toBe( displayFirstDeposit[ 3 ] ); // status + expect( csvFirstDeposit[ 4 ] ).toBe( + `"${ displayFirstDeposit[ 3 ] }"` + ); // status expect( csvFirstDeposit[ 5 ] ).toBe( `"${ displayFirstDeposit[ 4 ] }"` ); // bank account diff --git a/client/deposits/rename-notice/header-image.svg b/client/deposits/rename-notice/header-image.svg new file mode 100644 index 00000000000..8a96d1df244 --- /dev/null +++ b/client/deposits/rename-notice/header-image.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/deposits/rename-notice/index.tsx b/client/deposits/rename-notice/index.tsx new file mode 100644 index 00000000000..61ff61b142e --- /dev/null +++ b/client/deposits/rename-notice/index.tsx @@ -0,0 +1,88 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import React, { useState, useEffect } from 'react'; +import { TourKit } from '@woocommerce/components'; +import { useDispatch } from '@wordpress/data'; +import { createInterpolateElement } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import './style.scss'; + +export const PayoutsRenameNotice = () => { + const isPayoutsRenameNoticeDismissed = + wcpaySettings.isPayoutsRenameNoticeDismissed; + const { updateOptions } = useDispatch( 'wc/admin/options' ); + const [ showTour, setShowTour ] = useState( false ); + + const onClose = () => { + updateOptions( { + wcpay_payouts_rename_notice_dismissed: true, + } ); + setShowTour( false ); + wcpaySettings.isPayoutsRenameNoticeDismissed = true; + }; + + useEffect( () => { + if ( ! isPayoutsRenameNoticeDismissed ) { + setShowTour( true ); + } + }, [ isPayoutsRenameNoticeDismissed ] ); + + if ( ! showTour ) return null; + + return ( + Learn More.", + 'woocommerce-payments' + ), + { + link: ( + // eslint-disable-next-line jsx-a11y/anchor-has-content + + ), + } + ), + }, + }, + }, + ], + closeHandler: onClose, + } } + > + ); +}; diff --git a/client/deposits/rename-notice/style.scss b/client/deposits/rename-notice/style.scss new file mode 100644 index 00000000000..3a2c51b7334 --- /dev/null +++ b/client/deposits/rename-notice/style.scss @@ -0,0 +1,77 @@ +.wc-admin-payments-overview-payouts-rename-tour { + color: #1e1e1e; + + .woocommerce-tour-kit-step { + border-radius: 8px; + border: 1px solid #dcdcdc; + + /* Shadow / Popover */ + box-shadow: 0 2px 6px 0 rgba( 0, 0, 0, 0.05 ); + width: 257px; + padding-bottom: 0; + } + + .components-card__footer { + display: none; + } + + .tour-kit-frame__container { + box-shadow: none; + background: none; + } + + .components-elevation { + display: none; + } + + .woocommerce-tour-kit-step__body { + background-image: url( './header-image.svg' ); + background-repeat: no-repeat; + background-position-x: center; + background-position-y: 5px; + padding-bottom: 24px; + } + .woocommerce-tour-kit-step-navigation { + display: none; + } + h2 { + padding-top: 100px; + font-size: 14px; + line-height: 24px; + } + p.woocommerce-tour-kit-step__description { + font-size: 13px; + line-height: 18px; + margin-top: 8px; + } + .tour-kit-frame__arrow::before { + box-shadow: none !important; + } + + .tour-kit-frame__container[data-popper-placement^='bottom'] { + & > .tour-kit-frame__arrow { + background: #fff; + &::before { + border-top: 1px solid var( --gutenberg-gray-300, #ddd ); + border-left: 1px solid var( --gutenberg-gray-300, #ddd ); + } + } + } + + .tour-kit-frame__container[data-popper-placement^='right'] { + & > .tour-kit-frame__arrow { + background: #fff; + &::before { + border-bottom: 1px solid var( --gutenberg-gray-300, #ddd ); + border-left: 1px solid var( --gutenberg-gray-300, #ddd ); + } + } + } + + a { + display: block; + text-decoration: none; + margin-top: 12px; + padding-block: 11px; + } +} diff --git a/client/deposits/rename-notice/test/__snapshots__/index.tsx.snap b/client/deposits/rename-notice/test/__snapshots__/index.tsx.snap new file mode 100644 index 00000000000..8d2131ec55c --- /dev/null +++ b/client/deposits/rename-notice/test/__snapshots__/index.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PayoutsRenameNotice should render notice if isPayoutsRenameNoticeDismissed is false 1`] = ` +
    +
    + Tour Component +
    +
    +`; diff --git a/client/deposits/rename-notice/test/index.tsx b/client/deposits/rename-notice/test/index.tsx new file mode 100644 index 00000000000..9f9f2d0c7a8 --- /dev/null +++ b/client/deposits/rename-notice/test/index.tsx @@ -0,0 +1,49 @@ +/** @format */ +/** + * External dependencies + */ +import React from 'react'; +import { render } from '@testing-library/react'; + +/** + * Internal dependencies + */ +import { PayoutsRenameNotice } from '..'; + +jest.mock( '@wordpress/api-fetch', () => jest.fn() ); + +jest.mock( '@wordpress/data', () => ( { + useDispatch: jest.fn().mockReturnValue( { updateOptions: jest.fn() } ), +} ) ); + +jest.mock( '@woocommerce/components', () => ( { + TourKit: () =>
    Tour Component
    , +} ) ); + +declare const global: { + wcpaySettings: { + isPayoutsRenameNoticeDismissed: boolean; + }; +}; + +describe( 'PayoutsRenameNotice', () => { + afterEach( () => { + jest.clearAllMocks(); + } ); + + test( 'should render null if isPayoutsRenameNoticeDismissed is true', () => { + global.wcpaySettings = { + isPayoutsRenameNoticeDismissed: true, + }; + const { container } = render( ); + expect( container.firstChild ).toBeNull(); + } ); + + test( 'should render notice if isPayoutsRenameNoticeDismissed is false', () => { + global.wcpaySettings = { + isPayoutsRenameNoticeDismissed: false, + }; + const { container } = render( ); + expect( container ).toMatchSnapshot(); + } ); +} ); diff --git a/client/deposits/strings.ts b/client/deposits/strings.ts index f4cbfbfb3a6..7dbf7df2dad 100644 --- a/client/deposits/strings.ts +++ b/client/deposits/strings.ts @@ -12,12 +12,21 @@ import { __ } from '@wordpress/i18n'; import type { DepositStatus } from 'wcpay/types/deposits'; export const displayType = { - deposit: __( 'Deposit', 'woocommerce-payments' ), + deposit: __( 'Payout', 'woocommerce-payments' ), withdrawal: __( 'Withdrawal', 'woocommerce-payments' ), }; -export const displayStatus: Record< DepositStatus, string > = { - paid: __( 'Paid', 'woocommerce-payments' ), +/** + * Labels to display for each deposit status. + * + * 'deducted' represents a deposit of the type 'withdrawal' and status 'paid'. + */ +export const depositStatusLabels: Record< + DepositStatus | 'deducted', + string +> = { + paid: __( 'Completed (paid)', 'woocommerce-payments' ), + deducted: __( 'Completed (deducted)', 'woocommerce-payments' ), pending: __( 'Pending', 'woocommerce-payments' ), in_transit: __( 'In transit', 'woocommerce-payments' ), canceled: __( 'Canceled', 'woocommerce-payments' ), diff --git a/client/disputes/filters/index.tsx b/client/disputes/filters/index.tsx index 6e8288f2611..0f6fc09069f 100644 --- a/client/disputes/filters/index.tsx +++ b/client/disputes/filters/index.tsx @@ -9,7 +9,7 @@ import { getQuery } from '@woocommerce/navigation'; * Internal dependencies */ import { filters, advancedFilters, DisputesFilterType } from './config'; -import { formatCurrencyName } from '../../utils/currency'; +import { formatCurrencyName } from 'multi-currency/interface/functions'; interface DisputesFiltersProps { storeCurrencies?: string[]; diff --git a/client/disputes/filters/test/index.tsx b/client/disputes/filters/test/index.tsx index c122ba7eb3a..015f28aec19 100644 --- a/client/disputes/filters/test/index.tsx +++ b/client/disputes/filters/test/index.tsx @@ -12,7 +12,7 @@ import { getQuery, updateQueryString } from '@woocommerce/navigation'; * Internal dependencies */ import { DisputesFilters } from '../'; -import { formatCurrencyName } from '../../../utils/currency'; +import { formatCurrencyName } from 'multi-currency/interface/functions'; // TODO: this is a bit of a hack as we're mocking an old version of WC, we should relook at this. jest.mock( '@woocommerce/settings', () => ( { diff --git a/client/disputes/index.tsx b/client/disputes/index.tsx index 0832ee5515b..060afccce35 100644 --- a/client/disputes/index.tsx +++ b/client/disputes/index.tsx @@ -37,7 +37,10 @@ import Page from 'components/page'; import { TestModeNotice } from 'components/test-mode-notice'; import { reasons } from './strings'; import { formatStringValue } from 'utils'; -import { formatExplicitCurrency, formatExportAmount } from 'utils/currency'; +import { + formatExplicitCurrency, + formatExportAmount, +} from 'multi-currency/interface/functions'; import DisputesFilters from './filters'; import DownloadButton from 'components/download-button'; import disputeStatusMapping from 'components/dispute-status-chip/mappings'; diff --git a/client/disputes/info/index.tsx b/client/disputes/info/index.tsx index 7aa20ca6174..12f7ba0e64a 100644 --- a/client/disputes/info/index.tsx +++ b/client/disputes/info/index.tsx @@ -16,7 +16,7 @@ import OrderLink from 'components/order-link'; import { getDetailsURL } from 'components/details-link'; import { reasons } from '../strings'; import { formatStringValue } from 'utils'; -import { formatExplicitCurrency } from 'utils/currency'; +import { formatExplicitCurrency } from 'multi-currency/interface/functions'; import './style.scss'; import Loadable from 'components/loadable'; import { Dispute } from 'wcpay/types/disputes'; diff --git a/client/disputes/utils.ts b/client/disputes/utils.ts index e96251c7863..96a1ca40129 100644 --- a/client/disputes/utils.ts +++ b/client/disputes/utils.ts @@ -18,7 +18,10 @@ import { disputeAwaitingResponseStatuses, disputeUnderReviewStatuses, } from 'wcpay/disputes/filters/config'; -import { formatCurrency, formatExplicitCurrency } from 'wcpay/utils/currency'; +import { + formatCurrency, + formatExplicitCurrency, +} from 'multi-currency/interface/functions'; interface IsDueWithinProps { dueBy: CachedDispute[ 'due_by' ] | EvidenceDetails[ 'due_by' ]; diff --git a/client/express-checkout/blocks/components/apple-pay-preview.js b/client/express-checkout/blocks/components/apple-pay-preview.js deleted file mode 100644 index 247d5e2e6fe..00000000000 --- a/client/express-checkout/blocks/components/apple-pay-preview.js +++ /dev/null @@ -1,7 +0,0 @@ -/* eslint-disable max-len */ -const applePayImage = - "data:image/svg+xml,%3Csvg fill='none' xmlns='http://www.w3.org/2000/svg' viewBox='-0.5 -0.5 344 51'%3E%3Crect width='343' height='50' rx='8' fill='black'%3E%3C/rect%3E%3Crect width='343' height='50' rx='8' stroke='black'%3E%3C/rect%3E%3Cpath d='M155.748 19.8275C154.411 19.8275 153.333 20.636 152.637 20.636C151.907 20.636 150.93 19.8724 149.773 19.8724C147.572 19.8724 145.337 21.7029 145.337 25.1282C145.337 27.2733 146.168 29.5306 147.19 31.0018C148.055 32.2259 148.83 33.2366 149.93 33.2366C151.02 33.2366 151.503 32.5179 152.862 32.5179C154.232 32.5179 154.546 33.2142 155.748 33.2142C156.95 33.2142 157.747 32.1248 158.499 31.0467C159.33 29.8001 159.69 28.5872 159.701 28.5311C159.634 28.5086 157.343 27.5765 157.343 24.9485C157.343 22.68 159.139 21.6693 159.241 21.5906C158.061 19.8724 156.253 19.8275 155.748 19.8275ZM155.13 18.3787C155.669 17.7161 156.051 16.8177 156.051 15.908C156.051 15.7845 156.04 15.6609 156.017 15.5599C155.141 15.5936 154.063 16.1439 153.423 16.8963C152.929 17.4691 152.457 18.3787 152.457 19.2884C152.457 19.4232 152.48 19.5692 152.491 19.6141C152.547 19.6253 152.637 19.6365 152.727 19.6365C153.524 19.6365 154.535 19.0975 155.13 18.3787ZM164.115 16.8289V33.0345H167.013V27.7225H170.528C173.807 27.7225 176.098 25.5213 176.098 22.3094C176.098 19.0413 173.886 16.8289 170.652 16.8289H164.115ZM167.013 19.2547H169.888C171.977 19.2547 173.156 20.3216 173.156 22.3094C173.156 24.241 171.943 25.3192 169.877 25.3192H167.013V19.2547ZM181.535 31.0467C180.3 31.0467 179.412 30.429 179.412 29.3958C179.412 28.3963 180.142 27.8348 181.703 27.7337L184.477 27.554V28.5311C184.477 29.9573 183.219 31.0467 181.535 31.0467ZM180.715 33.2366C182.321 33.2366 183.669 32.5403 184.354 31.3499H184.545V33.0345H187.229V24.6453C187.229 22.0399 185.454 20.5013 182.299 20.5013C179.379 20.5013 177.346 21.8826 177.121 24.0501H179.749C180.008 23.2191 180.884 22.7698 182.164 22.7698C183.669 22.7698 184.477 23.4437 184.477 24.6453V25.6785L181.31 25.8694C178.323 26.0491 176.65 27.3294 176.65 29.553C176.65 31.7991 178.345 33.2366 180.715 33.2366ZM190.329 37.493C193.081 37.493 194.395 36.4822 195.439 33.4276L199.875 20.7484H196.933L194.069 30.3392H193.878L191.003 20.7484H187.948L192.34 33.0906L192.194 33.6297C191.834 34.764 191.172 35.2132 189.992 35.2132C189.801 35.2132 189.386 35.202 189.229 35.1683V37.4481C189.408 37.4818 190.161 37.493 190.329 37.493Z' fill='white'%3E%3C/path%3E%3C/svg%3E"; - -const ApplePayPreview = () => ; - -export default ApplePayPreview; diff --git a/client/express-checkout/blocks/components/express-checkout-component.js b/client/express-checkout/blocks/components/express-checkout-component.js index 6274a08d452..2ad91ee5881 100644 --- a/client/express-checkout/blocks/components/express-checkout-component.js +++ b/client/express-checkout/blocks/components/express-checkout-component.js @@ -76,6 +76,7 @@ const ExpressCheckoutComponent = ( { onClose, expressPaymentMethod = '', buttonAttributes, + isPreview = false, } ) => { const { buttonOptions, @@ -92,7 +93,7 @@ const ExpressCheckoutComponent = ( { onClose, setExpressPaymentError, } ); - + const onClickHandler = ! isPreview ? onButtonClick : () => {}; const onShippingAddressChange = ( event ) => shippingAddressChangeHandler( api, event, elements ); @@ -140,7 +141,7 @@ const ExpressCheckoutComponent = ( { ), ...getPaymentMethodsOverride( expressPaymentMethod ), } } - onClick={ onButtonClick } + onClick={ onClickHandler } onConfirm={ onConfirm } onReady={ onElementsReady } onCancel={ onCancel } diff --git a/client/express-checkout/blocks/components/express-checkout-container.js b/client/express-checkout/blocks/components/express-checkout-container.js index c2df0e55c6a..163e177c141 100644 --- a/client/express-checkout/blocks/components/express-checkout-container.js +++ b/client/express-checkout/blocks/components/express-checkout-container.js @@ -15,17 +15,17 @@ import { import '../express-checkout-element.scss'; const ExpressCheckoutContainer = ( props ) => { - const { api, billing, buttonAttributes } = props; + const { api, billing, buttonAttributes, isPreview } = props; const stripePromise = useMemo( () => { - return api.loadStripe( true ); + return api.loadStripeForExpressCheckout(); }, [ api ] ); const options = { mode: 'payment', paymentMethodCreation: 'manual', - amount: billing.cartTotal.value, - currency: billing.currency.code.toLowerCase(), + amount: ! isPreview ? billing.cartTotal.value : 10, + currency: ! isPreview ? billing.currency.code.toLowerCase() : 'usd', appearance: getExpressCheckoutButtonAppearance( buttonAttributes ), locale: getExpressCheckoutData( 'stripe' )?.locale ?? 'en', }; diff --git a/client/express-checkout/blocks/components/google-pay-preview.js b/client/express-checkout/blocks/components/google-pay-preview.js deleted file mode 100644 index fc110d67024..00000000000 --- a/client/express-checkout/blocks/components/google-pay-preview.js +++ /dev/null @@ -1,7 +0,0 @@ -/* eslint-disable max-len */ -const googlePayImage = - "data:image/svg+xml,%3Csvg width='343' height='50' viewBox='0 0 343 50' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='343' height='50' rx='8' fill='black'/%3E%3Cpath d='M94.9511 24.6726V31.7486H92.6902V14.2749H98.6838C100.203 14.2749 101.498 14.7778 102.558 15.7837C103.641 16.7895 104.183 18.0176 104.183 19.4679C104.183 20.9533 103.641 22.1813 102.558 23.1755C101.51 24.1696 100.215 24.6609 98.6838 24.6609H94.9511V24.6726ZM94.9511 16.4269V22.5205H98.7309C99.6258 22.5205 100.379 22.2164 100.968 21.6199C101.569 21.0234 101.875 20.2983 101.875 19.4796C101.875 18.6726 101.569 17.9591 100.968 17.3626C100.379 16.7427 99.6375 16.4386 98.7309 16.4386H94.9511V16.4269Z' fill='white'/%3E%3Cpath d='M110.094 19.3977C111.766 19.3977 113.085 19.8421 114.05 20.731C115.016 21.6199 115.499 22.8363 115.499 24.3802V31.7486H113.344V30.0878H113.25C112.319 31.4562 111.071 32.1345 109.517 32.1345C108.186 32.1345 107.079 31.7486 106.185 30.9649C105.29 30.1813 104.842 29.2106 104.842 28.041C104.842 26.8012 105.313 25.8188 106.255 25.0936C107.197 24.3568 108.457 23.9942 110.023 23.9942C111.366 23.9942 112.472 24.2398 113.332 24.731V24.2164C113.332 23.4328 113.026 22.7778 112.402 22.2281C111.778 21.6784 111.048 21.4094 110.212 21.4094C108.952 21.4094 107.951 21.9357 107.221 23L105.231 21.7603C106.326 20.1813 107.951 19.3977 110.094 19.3977ZM107.174 28.0761C107.174 28.6609 107.421 29.1521 107.927 29.538C108.422 29.924 109.011 30.1228 109.682 30.1228C110.636 30.1228 111.483 29.772 112.225 29.0702C112.967 28.3685 113.344 27.5497 113.344 26.6024C112.637 26.0527 111.66 25.772 110.4 25.772C109.482 25.772 108.716 25.9942 108.104 26.4269C107.48 26.8831 107.174 27.4328 107.174 28.0761Z' fill='white'/%3E%3Cpath d='M127.792 19.7837L120.256 37.0001H117.924L120.727 30.9767L115.758 19.7837H118.219L121.798 28.3685H121.845L125.331 19.7837H127.792Z' fill='white'/%3E%3Cpath d='M85.9586 23.2456C85.9586 22.5134 85.8926 21.8128 85.7702 21.1392H76.2936V24.9988L81.7513 25C81.53 26.2842 80.8176 27.3789 79.726 28.1087V30.6128H82.9748C84.8717 28.869 85.9586 26.2912 85.9586 23.2456Z' fill='%234285F4'/%3E%3Cpath d='M79.7272 28.1088C78.8229 28.7146 77.6583 29.069 76.2959 29.069C73.6642 29.069 71.4317 27.3076 70.6321 24.9333H67.2809V27.5158C68.9412 30.7883 72.3536 33.0339 76.2959 33.0339C79.0207 33.0339 81.3098 32.1439 82.9759 30.6117L79.7272 28.1088Z' fill='%2334A853'/%3E%3Cpath d='M70.3165 23.0176C70.3165 22.3509 70.4284 21.7065 70.6321 21.1006V18.5182H67.2809C66.5944 19.8714 66.2082 21.3989 66.2082 23.0176C66.2082 24.6363 66.5956 26.1638 67.2809 27.517L70.6321 24.9346C70.4284 24.3287 70.3165 23.6843 70.3165 23.0176Z' fill='%23FABB05'/%3E%3Cpath d='M76.2959 16.9649C77.7831 16.9649 79.1149 17.4737 80.1664 18.4678L83.0454 15.6105C81.2968 13.993 79.0172 13 76.2959 13C72.3548 13 68.9412 15.2456 67.2809 18.5181L70.6321 21.1006C71.4317 18.7263 73.6642 16.9649 76.2959 16.9649Z' fill='%23E94235'/%3E%3Cline x1='140.792' y1='12' x2='140.792' y2='38' stroke='%235F6368' stroke-width='2'/%3E%3Crect x='151.292' y='11.962' width='41' height='26' stroke='white'/%3E%3Cpath d='M187.766 23.7321C187.733 22.9139 187.369 22.1408 186.752 21.5792C186.135 21.0176 185.315 20.7123 184.467 20.7289C183.454 20.6861 182.434 20.7289 181.421 20.6984C181.149 20.6984 181.054 20.7779 181.01 21.0409C180.661 23.255 180.288 25.4631 179.92 27.6772C179.832 28.2154 179.749 28.7537 179.661 29.3042C179.721 29.3178 179.783 29.328 179.844 29.3347C180.87 29.3347 181.896 29.3347 182.916 29.3347C183.738 29.3504 184.55 29.1576 185.271 28.7756C185.992 28.3935 186.597 27.8355 187.025 27.1573C187.657 26.1261 187.918 24.9216 187.766 23.7321ZM184.98 26.405C184.783 26.8111 184.465 27.1511 184.067 27.3811C183.669 27.6111 183.208 27.7206 182.745 27.6955H182.111C182.219 27.0289 182.314 26.3989 182.422 25.7689C182.593 24.723 182.776 23.6709 182.941 22.6189C182.941 22.4171 183.036 22.3314 183.251 22.3498C183.365 22.359 183.479 22.359 183.593 22.3498C183.815 22.3177 184.042 22.3315 184.258 22.3903C184.475 22.4491 184.676 22.5515 184.848 22.6908C185.02 22.8301 185.16 23.0031 185.258 23.1984C185.356 23.3937 185.41 23.6069 185.417 23.8239C185.573 24.7059 185.424 25.6131 184.993 26.405' fill='white'/%3E%3Cpath d='M178.268 21.1081C177.831 20.9036 177.358 20.7831 176.874 20.7534C175.855 20.6922 174.829 20.7534 173.803 20.7106C173.537 20.7106 173.474 20.8084 173.442 21.0286C173.084 23.255 172.718 25.4793 172.347 27.7016C172.258 28.2338 172.176 28.772 172.081 29.3469C172.714 29.3469 173.347 29.3469 173.981 29.3469C174.215 29.3469 174.297 29.2674 174.329 29.0472C174.449 28.2338 174.601 27.4203 174.721 26.6007C174.721 26.405 174.829 26.3193 175.038 26.3438C175.12 26.3561 175.203 26.3561 175.285 26.3438C175.507 26.3438 175.595 26.3988 175.633 26.6129C175.722 27.1145 175.83 27.6099 175.95 28.1053C175.998 28.4255 176.15 28.7226 176.385 28.9535C176.619 29.1844 176.924 29.3372 177.254 29.3898C177.767 29.4233 178.282 29.411 178.793 29.3531C178.829 29.3432 178.861 29.3245 178.887 29.2987C178.912 29.2729 178.93 29.241 178.939 29.2063C178.977 28.772 178.996 28.3377 179.021 27.8912H178.704C178.598 27.9031 178.491 27.8944 178.388 27.8656C178.285 27.8368 178.19 27.7886 178.107 27.7236C178.023 27.6587 177.955 27.5784 177.904 27.4875C177.853 27.3965 177.822 27.2968 177.812 27.194C177.717 26.8453 177.66 26.4906 177.546 26.1481C177.476 25.9279 177.546 25.83 177.736 25.7199C178.164 25.4948 178.532 25.1773 178.812 24.7922C179.092 24.4071 179.276 23.9648 179.35 23.4997C179.521 22.4232 179.16 21.5241 178.293 21.1265L178.268 21.1081ZM176.817 24.2826C176.745 24.4438 176.621 24.5784 176.464 24.6665C176.307 24.7546 176.124 24.7915 175.944 24.7719C175.64 24.7564 175.336 24.7564 175.032 24.7719C175.158 24.0073 175.266 23.3039 175.393 22.6005C175.408 22.5626 175.431 22.5285 175.462 22.501C175.493 22.4734 175.53 22.453 175.57 22.4415C175.827 22.4171 176.086 22.4171 176.343 22.4415C176.529 22.4659 176.7 22.5528 176.826 22.687C176.952 22.8213 177.026 22.9943 177.033 23.1755C177.084 23.5543 176.999 23.9388 176.792 24.2642' fill='white'/%3E%3Cpath d='M171.061 27.2062C170.625 25.1266 170.188 23.0532 169.757 20.9675C169.713 20.7779 169.637 20.7106 169.428 20.7106C168.953 20.7106 168.478 20.7106 168.003 20.7106C167.907 20.6989 167.811 20.7184 167.728 20.7661C167.645 20.8138 167.582 20.8868 167.547 20.9736C166.724 22.5088 165.894 24.0318 165.071 25.567C165.027 25.6588 164.976 25.7444 164.925 25.8361L163.216 29.0106C163.165 29.1023 163.127 29.2002 163.057 29.347C163.811 29.347 164.514 29.347 165.21 29.347C165.286 29.347 165.381 29.243 165.419 29.1635C165.66 28.7047 165.894 28.2399 166.116 27.7628C166.143 27.6883 166.195 27.6247 166.264 27.5825C166.333 27.5402 166.415 27.5219 166.496 27.5304C167.205 27.5304 167.921 27.5304 168.636 27.5304C168.851 27.5304 168.921 27.6038 168.953 27.7934C169.016 28.2277 169.086 28.6619 169.174 29.0901C169.174 29.1879 169.288 29.347 169.358 29.347C170.055 29.347 170.757 29.347 171.498 29.347C171.498 29.194 171.46 29.0778 171.435 28.9616C171.315 28.35 171.188 27.7934 171.061 27.2062ZM167.047 25.8973C167.427 25.1266 167.794 24.3927 168.161 23.6587H168.25C168.37 24.3927 168.497 25.1266 168.624 25.8973H167.047Z' fill='white'/%3E%3Cpath d='M161.101 27.6712C160.883 27.7345 160.653 27.7492 160.428 27.7139C160.203 27.6787 159.99 27.5946 159.804 27.4679C159.618 27.3412 159.464 27.1752 159.354 26.9826C159.244 26.79 159.181 26.5758 159.169 26.3561C159.021 25.4427 159.16 24.5072 159.568 23.671C159.728 23.2847 160.004 22.9537 160.361 22.7213C160.718 22.4888 161.139 22.3658 161.569 22.3682H161.835C162.304 22.4049 162.773 22.4844 163.273 22.5517C163.45 22.0502 163.64 21.5303 163.83 21.0043C163.694 20.8051 163.504 20.6456 163.281 20.5432C163.057 20.4408 162.809 20.3993 162.564 20.4232H157.65L157.599 20.6495C158.2 20.8013 158.79 20.9913 159.366 21.2183C158.824 21.5117 158.349 21.9093 157.973 22.3866C157.03 23.6171 156.604 25.1469 156.782 26.6681C156.804 27.2214 156.996 27.7558 157.335 28.2026C157.673 28.6495 158.142 28.9884 158.682 29.1758C159.322 29.4124 160.008 29.5146 160.692 29.4756C161.377 29.4365 162.045 29.2572 162.652 28.9495C162.722 28.9128 162.817 28.821 162.811 28.7599C162.754 28.2706 162.678 27.7874 162.614 27.3286C162.089 27.451 161.614 27.5855 161.126 27.6712' fill='white'/%3E%3Cpath d='M203.482 28.956C203.17 28.956 202.876 28.896 202.6 28.776C202.336 28.656 202.102 28.494 201.898 28.29C201.694 28.086 201.532 27.852 201.412 27.588C201.292 27.312 201.232 27.018 201.232 26.706C201.232 26.394 201.292 26.106 201.412 25.842C201.532 25.566 201.694 25.326 201.898 25.122C202.102 24.918 202.336 24.756 202.6 24.636C202.876 24.516 203.17 24.456 203.482 24.456C203.794 24.456 204.088 24.516 204.364 24.636C204.64 24.756 204.88 24.918 205.084 25.122C205.288 25.326 205.45 25.566 205.57 25.842C205.69 26.106 205.75 26.394 205.75 26.706C205.75 27.018 205.69 27.312 205.57 27.588C205.45 27.852 205.288 28.086 205.084 28.29C204.88 28.494 204.64 28.656 204.364 28.776C204.088 28.896 203.794 28.956 203.482 28.956ZM210.882 28.956C210.57 28.956 210.276 28.896 210 28.776C209.736 28.656 209.502 28.494 209.298 28.29C209.094 28.086 208.932 27.852 208.812 27.588C208.692 27.312 208.632 27.018 208.632 26.706C208.632 26.394 208.692 26.106 208.812 25.842C208.932 25.566 209.094 25.326 209.298 25.122C209.502 24.918 209.736 24.756 210 24.636C210.276 24.516 210.57 24.456 210.882 24.456C211.194 24.456 211.488 24.516 211.764 24.636C212.04 24.756 212.28 24.918 212.484 25.122C212.688 25.326 212.85 25.566 212.97 25.842C213.09 26.106 213.15 26.394 213.15 26.706C213.15 27.018 213.09 27.312 212.97 27.588C212.85 27.852 212.688 28.086 212.484 28.29C212.28 28.494 212.04 28.656 211.764 28.776C211.488 28.896 211.194 28.956 210.882 28.956ZM218.283 28.956C217.971 28.956 217.677 28.896 217.401 28.776C217.137 28.656 216.903 28.494 216.699 28.29C216.495 28.086 216.333 27.852 216.213 27.588C216.093 27.312 216.033 27.018 216.033 26.706C216.033 26.394 216.093 26.106 216.213 25.842C216.333 25.566 216.495 25.326 216.699 25.122C216.903 24.918 217.137 24.756 217.401 24.636C217.677 24.516 217.971 24.456 218.283 24.456C218.595 24.456 218.889 24.516 219.165 24.636C219.441 24.756 219.681 24.918 219.885 25.122C220.089 25.326 220.251 25.566 220.371 25.842C220.491 26.106 220.551 26.394 220.551 26.706C220.551 27.018 220.491 27.312 220.371 27.588C220.251 27.852 220.089 28.086 219.885 28.29C219.681 28.494 219.441 28.656 219.165 28.776C218.889 28.896 218.595 28.956 218.283 28.956ZM225.683 28.956C225.371 28.956 225.077 28.896 224.801 28.776C224.537 28.656 224.303 28.494 224.099 28.29C223.895 28.086 223.733 27.852 223.613 27.588C223.493 27.312 223.433 27.018 223.433 26.706C223.433 26.394 223.493 26.106 223.613 25.842C223.733 25.566 223.895 25.326 224.099 25.122C224.303 24.918 224.537 24.756 224.801 24.636C225.077 24.516 225.371 24.456 225.683 24.456C225.995 24.456 226.289 24.516 226.565 24.636C226.841 24.756 227.081 24.918 227.285 25.122C227.489 25.326 227.651 25.566 227.771 25.842C227.891 26.106 227.951 26.394 227.951 26.706C227.951 27.018 227.891 27.312 227.771 27.588C227.651 27.852 227.489 28.086 227.285 28.29C227.081 28.494 226.841 28.656 226.565 28.776C226.289 28.896 225.995 28.956 225.683 28.956ZM235.566 31.908L240.984 22.188L240.948 22.116H235.008L235.044 20.226H243.18V22.224L237.294 32.826L235.566 31.908ZM249.263 32.826C248.831 32.826 248.399 32.766 247.967 32.646C247.535 32.526 247.127 32.34 246.743 32.088C246.371 31.824 246.035 31.494 245.735 31.098C245.435 30.702 245.207 30.228 245.051 29.676L246.923 28.902C247.091 29.55 247.379 30.048 247.787 30.396C248.195 30.744 248.687 30.918 249.263 30.918C249.551 30.918 249.827 30.87 250.091 30.774C250.367 30.678 250.607 30.546 250.811 30.378C251.015 30.198 251.177 29.994 251.297 29.766C251.417 29.526 251.477 29.262 251.477 28.974C251.477 28.686 251.411 28.422 251.279 28.182C251.159 27.942 250.991 27.738 250.775 27.57C250.559 27.402 250.301 27.27 250.001 27.174C249.713 27.078 249.401 27.03 249.065 27.03H248.003V25.176H248.957C249.245 25.176 249.509 25.14 249.749 25.068C250.001 24.984 250.223 24.87 250.415 24.726C250.607 24.582 250.757 24.402 250.865 24.186C250.973 23.958 251.027 23.7 251.027 23.412C251.027 22.92 250.847 22.536 250.487 22.26C250.139 21.972 249.695 21.828 249.155 21.828C248.855 21.828 248.591 21.87 248.363 21.954C248.147 22.038 247.961 22.152 247.805 22.296C247.649 22.44 247.517 22.602 247.409 22.782C247.313 22.95 247.235 23.124 247.175 23.304L245.339 22.53C245.435 22.242 245.585 21.948 245.789 21.648C245.993 21.336 246.251 21.054 246.563 20.802C246.875 20.55 247.241 20.346 247.661 20.19C248.093 20.022 248.591 19.938 249.155 19.938C249.731 19.938 250.259 20.022 250.739 20.19C251.219 20.358 251.633 20.592 251.981 20.892C252.329 21.192 252.599 21.546 252.791 21.954C252.983 22.362 253.079 22.806 253.079 23.286C253.079 23.634 253.031 23.952 252.935 24.24C252.851 24.528 252.731 24.786 252.575 25.014C252.419 25.23 252.245 25.416 252.053 25.572C251.861 25.728 251.663 25.86 251.459 25.968V26.076C251.735 26.196 251.999 26.352 252.251 26.544C252.503 26.724 252.719 26.94 252.899 27.192C253.091 27.444 253.241 27.732 253.349 28.056C253.457 28.368 253.511 28.71 253.511 29.082C253.511 29.622 253.403 30.126 253.187 30.594C252.971 31.05 252.671 31.446 252.287 31.782C251.915 32.106 251.471 32.358 250.955 32.538C250.439 32.73 249.875 32.826 249.263 32.826ZM261.209 32.538V30.108H255.449V28.524L261.047 20.226H263.225V28.236H264.773V30.108H263.225V32.538H261.209ZM261.209 23.196H261.101L257.699 28.236H261.209V23.196ZM271.097 32.826C270.473 32.826 269.897 32.73 269.369 32.538C268.841 32.346 268.385 32.088 268.001 31.764C267.617 31.428 267.317 31.038 267.101 30.594C266.885 30.138 266.777 29.646 266.777 29.118C266.777 28.758 266.825 28.428 266.921 28.128C267.029 27.816 267.173 27.534 267.353 27.282C267.533 27.03 267.737 26.808 267.965 26.616C268.205 26.412 268.457 26.244 268.721 26.112V26.004C268.301 25.728 267.941 25.368 267.641 24.924C267.341 24.48 267.191 23.976 267.191 23.412C267.191 22.92 267.287 22.464 267.479 22.044C267.671 21.612 267.941 21.24 268.289 20.928C268.637 20.616 269.051 20.376 269.531 20.208C270.011 20.028 270.533 19.938 271.097 19.938C271.661 19.938 272.183 20.028 272.663 20.208C273.143 20.376 273.557 20.616 273.905 20.928C274.253 21.24 274.523 21.612 274.715 22.044C274.907 22.464 275.003 22.92 275.003 23.412C275.003 23.976 274.853 24.48 274.553 24.924C274.253 25.368 273.893 25.728 273.473 26.004V26.112C273.737 26.244 273.983 26.412 274.211 26.616C274.451 26.808 274.661 27.03 274.841 27.282C275.021 27.534 275.159 27.816 275.255 28.128C275.363 28.428 275.417 28.758 275.417 29.118C275.417 29.646 275.309 30.138 275.093 30.594C274.877 31.038 274.577 31.428 274.193 31.764C273.809 32.088 273.353 32.346 272.825 32.538C272.297 32.73 271.721 32.826 271.097 32.826ZM271.097 25.212C271.637 25.212 272.087 25.062 272.447 24.762C272.819 24.45 273.005 24.03 273.005 23.502C273.005 22.962 272.819 22.542 272.447 22.242C272.087 21.942 271.637 21.792 271.097 21.792C270.557 21.792 270.101 21.942 269.729 22.242C269.369 22.542 269.189 22.962 269.189 23.502C269.189 24.03 269.369 24.45 269.729 24.762C270.101 25.062 270.557 25.212 271.097 25.212ZM271.097 30.936C271.421 30.936 271.721 30.888 271.997 30.792C272.273 30.696 272.513 30.564 272.717 30.396C272.933 30.228 273.095 30.024 273.203 29.784C273.323 29.532 273.383 29.262 273.383 28.974C273.383 28.686 273.323 28.422 273.203 28.182C273.083 27.93 272.921 27.72 272.717 27.552C272.513 27.384 272.273 27.252 271.997 27.156C271.721 27.06 271.421 27.012 271.097 27.012C270.773 27.012 270.473 27.06 270.197 27.156C269.921 27.252 269.681 27.384 269.477 27.552C269.273 27.72 269.111 27.93 268.991 28.182C268.871 28.422 268.811 28.686 268.811 28.974C268.811 29.262 268.865 29.532 268.973 29.784C269.093 30.024 269.255 30.228 269.459 30.396C269.675 30.564 269.921 30.696 270.197 30.792C270.473 30.888 270.773 30.936 271.097 30.936Z' fill='white'/%3E%3C/svg%3E%0A"; - -const GooglePayPreview = () => ; - -export default GooglePayPreview; diff --git a/client/express-checkout/blocks/hooks/use-express-checkout.js b/client/express-checkout/blocks/hooks/use-express-checkout.js index 090a16354a7..88f72e76829 100644 --- a/client/express-checkout/blocks/hooks/use-express-checkout.js +++ b/client/express-checkout/blocks/hooks/use-express-checkout.js @@ -68,6 +68,8 @@ export const useExpressCheckout = ( { }; } ), + allowedShippingCountries: getExpressCheckoutData( 'checkout' ) + .allowed_shipping_countries, }; // Click event from WC Blocks. diff --git a/client/express-checkout/blocks/index.js b/client/express-checkout/blocks/index.js index 5ae6fb829fe..764dc2292cd 100644 --- a/client/express-checkout/blocks/index.js +++ b/client/express-checkout/blocks/index.js @@ -8,9 +8,7 @@ import { __ } from '@wordpress/i18n'; */ import { PAYMENT_METHOD_NAME_EXPRESS_CHECKOUT_ELEMENT } from 'wcpay/checkout/constants'; import { getConfig } from 'wcpay/utils/checkout'; -import ApplePayPreview from './components/apple-pay-preview'; import ExpressCheckoutContainer from './components/express-checkout-container'; -import GooglePayPreview from './components/google-pay-preview'; import { checkPaymentMethodIsAvailable } from '../utils/checkPaymentMethodIsAvailable'; const expressCheckoutElementApplePay = ( api ) => ( { @@ -25,9 +23,16 @@ const expressCheckoutElementApplePay = ( api ) => ( { content: ( ), - edit: , + edit: ( + + ), supports: { features: getConfig( 'features' ), + style: [ 'height', 'borderRadius' ], }, canMakePayment: ( { cart } ) => { if ( typeof wcpayExpressCheckoutParams === 'undefined' ) { @@ -56,9 +61,16 @@ const expressCheckoutElementGooglePay = ( api ) => { expressPaymentMethod="googlePay" /> ), - edit: , + edit: ( + + ), supports: { features: getConfig( 'features' ), + style: [ 'height', 'borderRadius' ], }, canMakePayment: ( { cart } ) => { if ( typeof wcpayExpressCheckoutParams === 'undefined' ) { diff --git a/client/express-checkout/index.js b/client/express-checkout/index.js index f4efa4aa10f..535431b7fd1 100644 --- a/client/express-checkout/index.js +++ b/client/express-checkout/index.js @@ -304,6 +304,9 @@ jQuery( ( $ ) => { shippingAddressRequired: options.requestShipping, phoneNumberRequired: options.requestPhone, shippingRates, + allowedShippingCountries: getExpressCheckoutData( + 'checkout' + ).allowed_shipping_countries, }; onClickHandler( event ); diff --git a/client/express-checkout/utils/checkPaymentMethodIsAvailable.js b/client/express-checkout/utils/checkPaymentMethodIsAvailable.js index 29f809b731d..b592169da22 100644 --- a/client/express-checkout/utils/checkPaymentMethodIsAvailable.js +++ b/client/express-checkout/utils/checkPaymentMethodIsAvailable.js @@ -42,7 +42,7 @@ export const checkPaymentMethodIsAvailable = memoize( root.render( ( key: K ) => { - return window.wcpayExpressCheckoutParams?.[ key ] ?? null; + if ( typeof window.wcpayExpressCheckoutParams !== 'undefined' ) { + return window.wcpayExpressCheckoutParams[ key ] ?? null; + } else if ( typeof window.wc?.wcSettings !== 'undefined' ) { + return window.wc.wcSettings.getSetting( 'ece_data' )?.[ key ] ?? null; + } + + return null; }; /** diff --git a/client/globals.d.ts b/client/globals.d.ts index f00b521943a..0d10d7de86b 100644 --- a/client/globals.d.ts +++ b/client/globals.d.ts @@ -3,6 +3,7 @@ */ import type { MccsDisplayTreeItem, Country } from 'onboarding/types'; import { PaymentMethodToPluginsMap } from './components/duplicate-notice'; +import { WCPayExpressCheckoutParams } from './express-checkout/utils'; declare global { const wcpaySettings: { @@ -88,6 +89,7 @@ declare global { fraudProtection: { isWelcomeTourDismissed?: boolean; }; + isPayoutsRenameNoticeDismissed: boolean; progressiveOnboarding?: { isEnabled: boolean; isComplete: boolean; @@ -138,6 +140,7 @@ declare global { }; const wc: { + wcSettings: typeof wcSettingsModule; tracks: { recordEvent: ( eventName: string, @@ -186,6 +189,21 @@ declare global { siteTitle: string; }; + interface WcSettings { + ece_data?: WCPayExpressCheckoutParams; + woocommerce_payments_data: typeof wcpaySettings; + } + + const wcSettingsModule: { + getSetting: < + K extends keyof WcSettings, + T extends WcSettings[ K ] | undefined + >( + setting: K, + fallback?: T + ) => WcSettings[ K ] | T; + }; + interface Window { wcpaySettings: typeof wcpaySettings; wc: typeof wc; diff --git a/client/index.js b/client/index.js index 12d96efc666..c42dfd42788 100644 --- a/client/index.js +++ b/client/index.js @@ -23,7 +23,7 @@ import DisputesPage from 'disputes'; import RedirectToTransactionDetails from 'disputes/redirect-to-transaction-details'; import DisputeEvidencePage from 'disputes/evidence'; import AdditionalMethodsPage from 'wcpay/additional-methods-setup'; -import MultiCurrencySetupPage from 'wcpay/multi-currency-setup'; +import { MultiCurrencySetupPage } from 'multi-currency/interface/components'; import CardReadersPage from 'card-readers'; import CapitalPage from 'capital'; import OverviewPage from 'overview'; @@ -97,9 +97,9 @@ addFilter( pages.push( { container: DepositsPage, - path: '/payments/deposits', + path: '/payments/payouts', wpOpenMenu: menuID, - breadcrumbs: [ rootLink, __( 'Deposits', 'woocommerce-payments' ) ], + breadcrumbs: [ rootLink, __( 'Payouts', 'woocommerce-payments' ) ], navArgs: { id: 'wc-payments-deposits', }, @@ -107,19 +107,19 @@ addFilter( } ); pages.push( { container: DepositDetailsPage, - path: '/payments/deposits/details', + path: '/payments/payouts/details', wpOpenMenu: menuID, breadcrumbs: [ rootLink, [ - '/payments/deposits', - __( 'Deposits', 'woocommerce-payments' ), + '/payments/payouts', + __( 'Payouts', 'woocommerce-payments' ), ], - __( 'Deposit details', 'woocommerce-payments' ), + __( 'Payout details', 'woocommerce-payments' ), ], navArgs: { id: 'wc-payments-deposit-details', - parentPath: '/payments/deposits', + parentPath: '/payments/payouts', }, capability: 'manage_woocommerce', } ); diff --git a/client/multi-currency-setup/wizard/task-item.scss b/client/multi-currency-setup/wizard/task-item.scss deleted file mode 100644 index 9751a378ab6..00000000000 --- a/client/multi-currency-setup/wizard/task-item.scss +++ /dev/null @@ -1,17 +0,0 @@ -.wcpay-wizard-task { - &__visible-description-element { - position: absolute; - margin-left: 40px; - margin-top: 0; - margin-bottom: 1em; - - &.is-muted-color { - color: $gray-700; - } - - .components-external-link svg { - width: 1em; - height: 1em; - } - } -} diff --git a/client/multi-currency-setup/wizard/task-item.tsx b/client/multi-currency-setup/wizard/task-item.tsx deleted file mode 100644 index 93711e4c80f..00000000000 --- a/client/multi-currency-setup/wizard/task-item.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/** - * External dependencies - */ -import React, { useContext } from 'react'; -import classNames from 'classnames'; -import { Icon, check } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import WizardTaskContext from '../../additional-methods-setup/wizard/task/context'; -import './task-item.scss'; - -interface WizardTaskItemProps { - children: React.ReactNode; - title: string; - index: number; - visibleDescription: string; - className?: string; -} - -const WizardTaskItem: React.FC< WizardTaskItemProps > = ( { - children, - title, - index, - visibleDescription, - className, -} ) => { - const { isCompleted, isActive } = useContext( WizardTaskContext ); - - return ( -
  • -
    -
    -
    -
    - { index } -
    - -
    - { title } -
    - { visibleDescription && ! isActive && ( - - { visibleDescription } - - ) } -
    { children }
    -
  • - ); -}; - -export default WizardTaskItem; diff --git a/client/onboarding/steps/embedded-kyc.tsx b/client/onboarding/steps/embedded-kyc.tsx index e01ed82ca90..c14005f2d06 100644 --- a/client/onboarding/steps/embedded-kyc.tsx +++ b/client/onboarding/steps/embedded-kyc.tsx @@ -5,7 +5,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import { loadConnectAndInitialize, StripeConnectInstance, -} from '@stripe/connect-js'; +} from '@stripe/connect-js/pure'; import { ConnectAccountOnboarding, ConnectComponentsProvider, @@ -25,6 +25,10 @@ import { isPoEligible, } from 'wcpay/onboarding/utils'; import { getConnectUrl, getOverviewUrl } from 'wcpay/utils'; +import { + trackEmbeddedStepChange, + trackRedirected, +} from 'wcpay/onboarding/tracking'; interface Props { continueKyc?: boolean; @@ -57,6 +61,7 @@ const EmbeddedKyc: React.FC< Props > = ( { isEligible ); if ( accountSession && accountSession.clientSecret ) { + trackRedirected( isEligible, true ); return accountSession; // Return the full account session object } @@ -139,6 +144,10 @@ const EmbeddedKyc: React.FC< Props > = ( { locale, ] ); + const handleStepChange = ( step: string ) => { + trackEmbeddedStepChange( step ); + }; + const handleOnExit = async () => { const urlParams = new URLSearchParams( window.location.search ); const urlSource = @@ -192,6 +201,9 @@ const EmbeddedKyc: React.FC< Props > = ( { ) } onExit={ handleOnExit } + onStepChange={ ( stepChange ) => + handleStepChange( stepChange.step ) + } collectionOptions={ { fields: collectPayoutRequirements ? 'eventually_due' diff --git a/client/onboarding/steps/test/embedded-onboarding.tsx b/client/onboarding/steps/test/embedded-onboarding.tsx index bd3ee34b1bd..5d8804af111 100644 --- a/client/onboarding/steps/test/embedded-onboarding.tsx +++ b/client/onboarding/steps/test/embedded-onboarding.tsx @@ -4,7 +4,7 @@ import React from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import apiFetch from '@wordpress/api-fetch'; -import { loadConnectAndInitialize } from '@stripe/connect-js'; +import { loadConnectAndInitialize } from '@stripe/connect-js/pure'; /** * Internal dependencies @@ -12,7 +12,7 @@ import { loadConnectAndInitialize } from '@stripe/connect-js'; import EmbeddedKyc from '../embedded-kyc'; jest.mock( '@wordpress/api-fetch' ); -jest.mock( '@stripe/connect-js', () => ( { +jest.mock( '@stripe/connect-js/pure', () => ( { loadConnectAndInitialize: jest.fn(), } ) ); diff --git a/client/onboarding/tracking.ts b/client/onboarding/tracking.ts index 1250e4c5a16..a370a1449b2 100644 --- a/client/onboarding/tracking.ts +++ b/client/onboarding/tracking.ts @@ -46,11 +46,32 @@ export const trackStepCompleted = ( step: string ): void => { trackedSteps.add( step ); }; -export const trackRedirected = ( isPoEligible: boolean ): void => { +export const trackRedirected = ( + isPoEligible: boolean, + isEmbedded = false +): void => { const urlParams = new URLSearchParams( window.location.search ); recordEvent( 'wcpay_onboarding_flow_redirected', { is_po_eligible: isPoEligible, + is_embedded_onboarding: isEmbedded, + elapsed: elapsed( startTime ), + source: + urlParams.get( 'source' )?.replace( /[^\w-]+/g, '' ) || 'unknown', + } ); +}; + +/** + * Track a change in the embedded onboarding step. + * + * @param step The current step in the embedded onboarding flow. See: + * https://docs.stripe.com/connect/supported-embedded-components/account-onboarding#step-values + */ +export const trackEmbeddedStepChange = ( step: string ): void => { + const urlParams = new URLSearchParams( window.location.search ); + + recordEvent( 'wcpay_onboarding_flow_embedded_step_change', { + step: step, elapsed: elapsed( startTime ), source: urlParams.get( 'source' )?.replace( /[^\w-]+/g, '' ) || 'unknown', diff --git a/client/order/refund-confirm-modal/index.js b/client/order/refund-confirm-modal/index.js index fc589feb3c1..f7d8c66de07 100644 --- a/client/order/refund-confirm-modal/index.js +++ b/client/order/refund-confirm-modal/index.js @@ -115,7 +115,7 @@ const RefundConfirmationModal = ( { { sprintf( /* translators: %s: WooPayments */ __( - "Issue a full refund back to your customer's credit card using %s. " + + "Issue a full refund back to your customer's payment method using %s. " + 'This action can not be undone. To issue a partial refund, click "Cancel", and use ' + 'the "Refund" button in the order details below.', 'woocommerce-payments' diff --git a/client/overview/index.js b/client/overview/index.js index f6d5afd4a72..edb215993c7 100644 --- a/client/overview/index.js +++ b/client/overview/index.js @@ -32,6 +32,7 @@ import { useDisputes, useGetSettings, useSettings } from 'data'; import SandboxModeSwitchToLiveNotice from 'wcpay/components/sandbox-mode-switch-to-live-notice'; import './style.scss'; import BannerNotice from 'wcpay/components/banner-notice'; +import { PayoutsRenameNotice } from 'wcpay/deposits/rename-notice'; const OverviewPageError = () => { const queryParams = getQuery(); @@ -194,6 +195,7 @@ const OverviewPage = () => { { showConnectionSuccess && } { ! accountRejected && ! accountUnderReview && ( + { showTaskList && ( diff --git a/client/overview/modal/progressive-onboarding-eligibility/index.tsx b/client/overview/modal/progressive-onboarding-eligibility/index.tsx index 564e8494a70..d4b3f79021f 100644 --- a/client/overview/modal/progressive-onboarding-eligibility/index.tsx +++ b/client/overview/modal/progressive-onboarding-eligibility/index.tsx @@ -82,7 +82,7 @@ const ProgressiveOnboardingEligibilityModal: React.FC = () => {

    { __( - 'Start selling now and fast track the setup process, or continue the process to set up deposits with WooPayments.', + 'Start selling now and fast track the setup process, or continue the process to set up payouts with WooPayments.', 'woocommerce-payments' ) }

    @@ -120,14 +120,14 @@ const ProgressiveOnboardingEligibilityModal: React.FC = () => { { __( 'Flexible process', 'woocommerce-payments' ) } { __( - 'You have a $5,000 balance limit or 30 days from your first transaction to verify and set up deposits in your account.', + 'You have a $5,000 balance limit or 30 days from your first transaction to verify and set up payouts in your account.', 'woocommerce-payments' ) }
    @@ -1441,7 +1441,7 @@ exports[`PaymentDetailsTimeline renders subscription fee correctly 1`] = ` - $0.66 will be added to a future deposit. + $0.66 will be added to a future payout.
    - Net deposit: $0.66 + Net payout: $0.66
    diff --git a/client/payment-details/timeline/test/__snapshots__/map-events.js.snap b/client/payment-details/timeline/test/__snapshots__/map-events.js.snap index 3d0a3862088..e9c43d19b15 100644 --- a/client/payment-details/timeline/test/__snapshots__/map-events.js.snap +++ b/client/payment-details/timeline/test/__snapshots__/map-events.js.snap @@ -14,9 +14,9 @@ exports[`mapTimelineEvents Multi-Currency events formats captured events with fe "headline": $20.97 USD was added to your - Apr 2, 2020 deposit + Apr 2, 2020 payout . , @@ -27,7 +27,7 @@ exports[`mapTimelineEvents Multi-Currency events formats captured events with fe "1.00 EUR → 1.19944 USD: $21.59 USD", "Fee (2.9% + $0.30): -$0.62", undefined, - "Net deposit: $20.97 USD", + "Net payout: $20.97 USD", ], "date": 2020-04-01T14:37:54.000Z, "headline": "A payment of €18.00 EUR was successfully charged.", @@ -52,9 +52,9 @@ exports[`mapTimelineEvents Multi-Currency events formats captured events without "headline": $20.97 USD was added to your - Apr 2, 2020 deposit + Apr 2, 2020 payout . , @@ -65,7 +65,7 @@ exports[`mapTimelineEvents Multi-Currency events formats captured events without "1.00 EUR → 1.19944 USD: $21.59 USD", "Fee: €0.52", undefined, - "Net deposit: $20.97 USD", + "Net payout: $20.97 USD", ], "date": 2020-04-01T14:37:54.000Z, "headline": "A payment of €18.00 EUR was successfully charged.", @@ -91,7 +91,7 @@ exports[`mapTimelineEvents Multi-Currency events formats dispute_needs_response "Fee: $15.00", ], "date": 2020-04-02T02:06:14.000Z, - "headline": "$36.60 USD will be deducted from a future deposit.", + "headline": "$36.60 USD will be deducted from a future payout.", "icon": , }, { @@ -122,9 +122,9 @@ exports[`mapTimelineEvents Multi-Currency events formats dispute_won events 1`] "headline": $44.99 USD was added to your - Apr 5, 2020 deposit + Apr 5, 2020 payout . , @@ -152,7 +152,7 @@ exports[`mapTimelineEvents Multi-Currency events formats full_refund events 1`] { "body": [], "date": 2020-04-04T13:51:06.000Z, - "headline": "21,64 $ USD will be deducted from a future deposit.", + "headline": "21,64 $ USD will be deducted from a future payout.", "icon": , }, { @@ -180,7 +180,7 @@ exports[`mapTimelineEvents Multi-Currency events formats partial_refund events 1 { "body": [], "date": 2020-04-03T18:58:01.000Z, - "headline": "6,00 $ USD will be deducted from a future deposit.", + "headline": "6,00 $ USD will be deducted from a future payout.", "icon": , }, { @@ -374,9 +374,9 @@ exports[`mapTimelineEvents single currency events formats captured events with f "headline": $59.50 USD was added to your - Apr 2, 2020 deposit + Apr 2, 2020 payout . , @@ -414,7 +414,7 @@ exports[`mapTimelineEvents single currency events formats captured events with f , - "Net deposit: $59.50 USD", + "Net payout: $59.50 USD", ], "date": 2020-04-01T14:37:54.000Z, "headline": "A payment of $63.00 USD was successfully charged.", @@ -439,9 +439,9 @@ exports[`mapTimelineEvents single currency events formats captured events with j "headline": $59.50 USD was added to your - Apr 2, 2020 deposit + Apr 2, 2020 payout . , @@ -452,7 +452,7 @@ exports[`mapTimelineEvents single currency events formats captured events with j undefined, "Base fee (1.95% + $0.15): -$3.50", undefined, - "Net deposit: $59.50 USD", + "Net payout: $59.50 USD", ], "date": 2020-04-01T14:37:54.000Z, "headline": "A payment of $63.00 USD was successfully charged.", @@ -477,9 +477,9 @@ exports[`mapTimelineEvents single currency events formats captured events withou "headline": $59.50 USD was added to your - Apr 2, 2020 deposit + Apr 2, 2020 payout . , @@ -490,7 +490,7 @@ exports[`mapTimelineEvents single currency events formats captured events withou undefined, "Fee: $3.50", undefined, - "Net deposit: $59.50 USD", + "Net payout: $59.50 USD", ], "date": 2020-04-01T14:37:54.000Z, "headline": "A payment of $63.00 USD was successfully charged.", @@ -535,7 +535,7 @@ exports[`mapTimelineEvents single currency events formats dispute_needs_response "Fee: $15.00", ], "date": 2020-04-02T02:06:14.000Z, - "headline": "$110.00 USD will be deducted from a future deposit.", + "headline": "$110.00 USD will be deducted from a future payout.", "icon": , }, { @@ -566,9 +566,9 @@ exports[`mapTimelineEvents single currency events formats dispute_won events 1`] "headline": $115.00 USD was added to your - Apr 5, 2020 deposit + Apr 5, 2020 payout . , @@ -599,7 +599,7 @@ exports[`mapTimelineEvents single currency events formats financing paydown even , ], "date": 2022-02-01T12:04:04.000Z, - "headline": "$110.00 will be subtracted from a future deposit.", + "headline": "$110.00 will be subtracted from a future payout.", "icon": , }, ] @@ -616,7 +616,7 @@ exports[`mapTimelineEvents single currency events formats full_refund events 1`] { "body": [], "date": 2020-04-04T13:51:06.000Z, - "headline": "$100.00 USD will be deducted from a future deposit.", + "headline": "$100.00 USD will be deducted from a future payout.", "icon": , }, { @@ -644,7 +644,7 @@ exports[`mapTimelineEvents single currency events formats partial_refund events { "body": [], "date": 2020-04-03T18:58:01.000Z, - "headline": "$50.00 USD will be deducted from a future deposit.", + "headline": "$50.00 USD will be deducted from a future payout.", "icon": , }, { @@ -675,9 +675,9 @@ exports[`mapTimelineEvents single currency events in person payments - tap to pa "headline": $19.19 USD was added to your - Apr 2, 2020 deposit + Apr 2, 2020 payout . , @@ -699,7 +699,7 @@ exports[`mapTimelineEvents single currency events in person payments - tap to pa , - "Net deposit: $19.19 USD", + "Net payout: $19.19 USD", ], "date": 2020-04-01T14:37:54.000Z, "headline": "A payment of $19.80 USD was successfully charged.", @@ -724,9 +724,9 @@ exports[`mapTimelineEvents single currency events should not render fee breakup "headline": $59.50 USD was added to your - Apr 2, 2020 deposit + Apr 2, 2020 payout . , @@ -737,7 +737,7 @@ exports[`mapTimelineEvents single currency events should not render fee breakup undefined, "Fee (1.95% + $0.15): -$3.50", undefined, - "Net deposit: $59.50 USD", + "Net payout: $59.50 USD", ], "date": 2020-04-01T14:37:54.000Z, "headline": "A payment of $63.00 USD was successfully charged.", diff --git a/client/payment-request/blocks/index.js b/client/payment-request/blocks/index.js index 595f46cdeb4..a234e3127e9 100644 --- a/client/payment-request/blocks/index.js +++ b/client/payment-request/blocks/index.js @@ -25,7 +25,10 @@ const paymentRequestPaymentMethod = ( api ) => ( { ), gatewayId: 'woocommerce_payments', content: ( - + ), edit: , canMakePayment: ( cartData ) => { @@ -46,7 +49,7 @@ const paymentRequestPaymentMethod = ( api ) => ( { return false; } - return api.loadStripe( true ).then( ( stripe ) => { + return api.loadStripeForExpressCheckout().then( ( stripe ) => { // Create a payment request and check if we can make a payment to determine whether to // show the Payment Request Button or not. This is necessary because a browser might be // able to load the Stripe JS object, but not support Payment Requests. diff --git a/client/product-details/bnpl-site-messaging/index.js b/client/product-details/bnpl-site-messaging/index.js index 36cb845fb71..1bbe51e0edf 100644 --- a/client/product-details/bnpl-site-messaging/index.js +++ b/client/product-details/bnpl-site-messaging/index.js @@ -55,12 +55,11 @@ export const initializeBnplSiteMessaging = async () => { isCart, isCartBlock, cartTotal, - minimumOrderAmount, + isBnplAvailable, } = window.wcpayStripeSiteMessaging; let amount; let elementLocation = 'bnplProductPage'; - const minOrderAmount = parseInt( minimumOrderAmount, 10 ) || 0; const paymentMessageContainer = document.getElementById( 'payment-method-message' ); @@ -71,7 +70,7 @@ export const initializeBnplSiteMessaging = async () => { } else { amount = parseInt( productVariations.base_product.amount, 10 ) || 0; - if ( amount < minOrderAmount ) { + if ( ! isBnplAvailable ) { paymentMessageContainer.style.setProperty( 'display', 'none' ); } } diff --git a/client/product-details/index.js b/client/product-details/index.js index 93358a26f3b..b686e1a342f 100644 --- a/client/product-details/index.js +++ b/client/product-details/index.js @@ -104,13 +104,29 @@ jQuery( async function ( $ ) { 'get_cart_total' ), { - security: window.wcpayStripeSiteMessaging.nonce, + security: window.wcpayStripeSiteMessaging.nonce.get_cart_total, + } + ); + }; + + const isBnplAvailable = ( price, currency, country ) => { + return request( + buildAjaxURL( + window.wcpayStripeSiteMessaging.wcAjaxUrl, + 'check_bnpl_availability' + ), + { + security: + window.wcpayStripeSiteMessaging.nonce.is_bnpl_available, + price: price, + currency: currency, + country: country, } ); }; // Update BNPL message based on the quantity change - quantityInput.on( 'change', ( event ) => { + quantityInput.on( 'change', async ( event ) => { let amount = baseProductAmount; const variationId = $( VARIATION_ID_SELECTOR ).val(); @@ -123,6 +139,22 @@ jQuery( async function ( $ ) { } updateBnplPaymentMessage( amount, productCurrency, event.target.value ); + + // Check if changes in quantity/price affect BNPL availability and show/hide BNPL messaging accordingly. + try { + const response = await isBnplAvailable( + amount * event.target.value, + productCurrency, + window.wcpayStripeSiteMessaging.country + ); + if ( response.success && response.data.is_available ) { + $( '#payment-method-message' ).slideDown(); + } else { + $( '#payment-method-message' ).slideUp(); + } + } catch { + // Do nothing. + } } ); $( document.body ).on( 'updated_cart_totals', () => { diff --git a/client/settings/deposits/index.js b/client/settings/deposits/index.js index 05c114f79fd..19ad1956419 100644 --- a/client/settings/deposits/index.js +++ b/client/settings/deposits/index.js @@ -131,17 +131,17 @@ const CustomizeDepositSchedule = () => {

    { depositScheduleInterval === 'monthly' && __( - 'Deposits scheduled on a weekend will be sent on the next business day.', + 'Payouts scheduled on a weekend will be sent on the next business day.', 'woocommerce-payments' ) } { depositScheduleInterval === 'weekly' && __( - 'Deposits that fall on a holiday will initiate on the next business day.', + 'Payouts that fall on a holiday will initiate on the next business day.', 'woocommerce-payments' ) } { depositScheduleInterval === 'daily' && __( - 'Deposits will occur every business day.', + 'Payouts will occur every business day.', 'woocommerce-payments' ) }

    @@ -161,14 +161,14 @@ const DepositsSchedule = () => { { interpolateComponents( { mixedString: __( - 'Deposit scheduling is currently unavailable for your store. {{learnMoreLink}}Learn more{{/learnMoreLink}}', + 'Payout scheduling is currently unavailable for your store. {{learnMoreLink}}Learn more{{/learnMoreLink}}', 'woocommerce-payments' ), components: { learnMoreLink: ( // eslint-disable-next-line jsx-a11y/anchor-has-content @@ -183,15 +183,15 @@ const DepositsSchedule = () => { { interpolateComponents( { mixedString: __( - 'Your first deposit will be held for 7-14 days. ' + - 'Deposit scheduling will be available after this period. {{learnMoreLink}}Learn more{{/learnMoreLink}}', + 'Your first payout will be held for 7-14 days. ' + + 'Payout scheduling will be available after this period. {{learnMoreLink}}Learn more{{/learnMoreLink}}', 'woocommerce-payments' ), components: { learnMoreLink: ( // eslint-disable-next-line jsx-a11y/anchor-has-content @@ -220,13 +220,13 @@ const Deposits = () => { return ( -

    { __( 'Deposit schedule', 'woocommerce-payments' ) }

    +

    { __( 'Payout schedule', 'woocommerce-payments' ) }

    - { __( 'Deposit bank account', 'woocommerce-payments' ) } + { __( 'Payout bank account', 'woocommerce-payments' ) }

    { hasErroredExternalAccount ? ( { ) : (

    { __( - 'Manage and update your deposit account information to receive payments and deposits.', + 'Manage and update your bank account information to receive payouts.', 'woocommerce-payments' ) }{ ' ' } { accountLink && ( diff --git a/client/settings/deposits/test/index.test.js b/client/settings/deposits/test/index.test.js index 1bd3bb9d101..f562bceee31 100644 --- a/client/settings/deposits/test/index.test.js +++ b/client/settings/deposits/test/index.test.js @@ -108,7 +108,7 @@ describe( 'Deposits', () => { ); const depositsMessage = screen.getByText( - /Deposit scheduling is currently unavailable for your store/, + /Payout scheduling is currently unavailable for your store/, { ignore: '.a11y-speak-region', } @@ -128,7 +128,7 @@ describe( 'Deposits', () => { ); const depositsMessage = screen.getByText( - /Deposit scheduling is currently unavailable for your store/, + /Payout scheduling is currently unavailable for your store/, { ignore: '.a11y-speak-region', } @@ -146,7 +146,7 @@ describe( 'Deposits', () => { ); const depositsMessage = screen.getByText( - /Deposit scheduling is currently unavailable for your store/, + /Payout scheduling is currently unavailable for your store/, { ignore: '.a11y-speak-region', } @@ -165,7 +165,7 @@ describe( 'Deposits', () => { ); const depositsMessage = screen.getByText( - /Your first deposit will be held for/, + /Your first payout will be held for/, { ignore: '.a11y-speak-region', } @@ -184,7 +184,7 @@ describe( 'Deposits', () => { ); expect( - screen.queryByText( /Your first deposit will be held for/, { + screen.queryByText( /Your first payout will be held for/, { ignore: '.a11y-speak-region', } ) ).toBeFalsy(); @@ -285,7 +285,7 @@ describe( 'Deposits', () => { ); const depositsMessage = screen.getByText( - /Deposits are currently paused because a recent deposit failed./, + /Payouts are currently paused because a recent payout failed./, { ignore: '.a11y-speak-region', } @@ -294,7 +294,7 @@ describe( 'Deposits', () => { expect( screen.queryByText( - /Manage and update your deposit account information to receive payments and deposits./, + /Manage and update your bank account information to receive payouts./, { ignore: '.a11y-speak-region', } @@ -311,7 +311,7 @@ describe( 'Deposits', () => { expect( screen.queryByText( - /Deposits are currently paused because a recent deposit failed./, + /Payouts are currently paused because a recent payout failed./, { ignore: '.a11y-speak-region', } @@ -319,7 +319,7 @@ describe( 'Deposits', () => { ).toBeFalsy(); const depositsMessage = screen.getByText( - /Manage and update your deposit account information to receive payments and deposits./, + /Manage and update your bank account information to receive payouts./, { ignore: '.a11y-speak-region', } @@ -352,7 +352,7 @@ describe( 'Deposits', () => { ); const depositsMessage = screen.getByText( - /Deposits are currently paused because a recent deposit failed./, + /Payouts are currently paused because a recent payout failed./, { ignore: '.a11y-speak-region', } @@ -361,7 +361,7 @@ describe( 'Deposits', () => { expect( screen.queryByText( - /Manage and update your deposit account information to receive payments and deposits./, + /Manage and update your bank account information to receive payouts./, { ignore: '.a11y-speak-region', } @@ -395,7 +395,7 @@ describe( 'Deposits', () => { expect( screen.queryByText( - /Deposits are currently paused because a recent deposit failed./, + /Payouts are currently paused because a recent payout failed./, { ignore: '.a11y-speak-region', } @@ -403,7 +403,7 @@ describe( 'Deposits', () => { ).toBeFalsy(); const depositsMessage = screen.getByText( - /Manage and update your deposit account information to receive payments and deposits./, + /Manage and update your bank account information to receive payouts./, { ignore: '.a11y-speak-region', } diff --git a/client/settings/express-checkout-settings/payment-request-button-preview.js b/client/settings/express-checkout-settings/payment-request-button-preview.js index a587348c79d..1c2c2f2e4df 100644 --- a/client/settings/express-checkout-settings/payment-request-button-preview.js +++ b/client/settings/express-checkout-settings/payment-request-button-preview.js @@ -43,7 +43,10 @@ const WooPayButtonPreview = ( { size, buttonType, theme, radius } ) => ( buttonSizeToPxMap[ size ] || buttonSizeToPxMap.medium }px`, size, - radius, + } } + buttonAttributes={ { + height: buttonSizeToPxMap[ size ] || buttonSizeToPxMap.medium, + borderRadius: radius, } } /> ); diff --git a/client/settings/fraud-protection/advanced-settings/allow-countries-notice.tsx b/client/settings/fraud-protection/advanced-settings/allow-countries-notice.tsx index bd03bea132c..e35671b83f2 100644 --- a/client/settings/fraud-protection/advanced-settings/allow-countries-notice.tsx +++ b/client/settings/fraud-protection/advanced-settings/allow-countries-notice.tsx @@ -45,7 +45,7 @@ interface AllowedCountriesNoticeProps { const AllowedCountriesNotice: React.FC< AllowedCountriesNoticeProps > = ( { setting, } ) => { - const { protectionSettingsUI, protectionSettingsChanged } = useContext( + const { protectionSettingsUI } = useContext( FraudPreventionSettingsContext ); const [ isBlocking, setIsBlocking ] = useState( @@ -53,7 +53,7 @@ const AllowedCountriesNotice: React.FC< AllowedCountriesNoticeProps > = ( { ); useEffect( () => { setIsBlocking( protectionSettingsUI[ setting ]?.block ?? false ); - }, [ protectionSettingsUI, setting, protectionSettingsChanged ] ); + }, [ protectionSettingsUI, setting ] ); const supportedCountriesType = getSupportedCountriesType(); const settingCountries = getSettingCountries(); diff --git a/client/settings/fraud-protection/advanced-settings/cards/order-items-threshold.tsx b/client/settings/fraud-protection/advanced-settings/cards/order-items-threshold.tsx index 31b4c7be8b6..7b730a06057 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/order-items-threshold.tsx +++ b/client/settings/fraud-protection/advanced-settings/cards/order-items-threshold.tsx @@ -1,14 +1,7 @@ /** * External dependencies */ -import React, { - useContext, - useEffect, - useState, - useMemo, - Dispatch, - SetStateAction, -} from 'react'; +import React, { useContext, useMemo, Dispatch, SetStateAction } from 'react'; import { __ } from '@wordpress/i18n'; import { TextControl } from '@wordpress/components'; @@ -36,7 +29,6 @@ const OrderItemsThresholdCustomForm: React.FC< OrderItemsThresholdCustomFormProp const { protectionSettingsUI, setProtectionSettingsUI, - setProtectionSettingsChanged, setIsDirty, } = useContext( FraudPreventionSettingsContext ); @@ -48,33 +40,11 @@ const OrderItemsThresholdCustomForm: React.FC< OrderItemsThresholdCustomFormProp [ protectionSettingsUI, setting ] ); - const minItemsTemp = parseInt( settingUI.min_items + '', 10 ); - const maxItemsTemp = parseInt( settingUI.max_items + '', 10 ); + const minItems = parseInt( settingUI?.min_items + '', 10 ); + const maxItems = parseInt( settingUI?.max_items + '', 10 ); - const [ minItemsCount, setMinItemsCount ] = useState( - isNaN( minItemsTemp ) ? '' : minItemsTemp - ); - const [ maxItemsCount, setMaxItemsCount ] = useState( - isNaN( maxItemsTemp ) ? '' : maxItemsTemp - ); - - useEffect( () => { - settingUI.min_items = minItemsCount - ? parseInt( minItemsCount + '', 10 ) - : minItemsCount; - settingUI.max_items = maxItemsCount - ? parseInt( maxItemsCount + '', 10 ) - : maxItemsCount; - setProtectionSettingsUI( protectionSettingsUI ); - setProtectionSettingsChanged( ( prev ) => ! prev ); - }, [ - settingUI, - minItemsCount, - maxItemsCount, - protectionSettingsUI, - setProtectionSettingsUI, - setProtectionSettingsChanged, - ] ); + const minItemsCount = isNaN( minItems ) ? '' : minItems; + const maxItemsCount = isNaN( maxItems ) ? '' : maxItems; const isItemRangeEmpty = ! parseInt( minItemsCount + '', 10 ) && @@ -82,6 +52,17 @@ const OrderItemsThresholdCustomForm: React.FC< OrderItemsThresholdCustomFormProp const isMinGreaterThanMax = parseInt( minItemsCount + '', 10 ) > parseInt( maxItemsCount + '', 10 ); + const handleInputChange = ( name: string ) => ( val: string ) => { + setProtectionSettingsUI( ( settings ) => ( { + ...settings, + [ setting ]: { + ...settings[ setting ], + [ name ]: val ? parseInt( val + '', 10 ) : val, + }, + } ) ); + setIsDirty( true ); + }; + return (

    Limits @@ -98,10 +79,7 @@ const OrderItemsThresholdCustomForm: React.FC< OrderItemsThresholdCustomFormProp placeholder={ '0' } value={ minItemsCount } type="number" - onChange={ ( value ) => { - setMinItemsCount( value ); - setIsDirty( true ); - } } + onChange={ handleInputChange( 'min_items' ) } onKeyDown={ ( e ) => /^[+-.,e]$/m.test( e.key ) && e.preventDefault() } @@ -125,10 +103,7 @@ const OrderItemsThresholdCustomForm: React.FC< OrderItemsThresholdCustomFormProp placeholder={ '0' } type="number" value={ maxItemsCount } - onChange={ ( value ) => { - setMaxItemsCount( value ); - setIsDirty( true ); - } } + onChange={ handleInputChange( 'max_items' ) } onKeyDown={ ( e ) => /^[+-.,e]$/m.test( e.key ) && e.preventDefault() } diff --git a/client/settings/fraud-protection/advanced-settings/cards/purchase-price-threshold.tsx b/client/settings/fraud-protection/advanced-settings/cards/purchase-price-threshold.tsx index 5c47153e0fb..828d1bbf5c8 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/purchase-price-threshold.tsx +++ b/client/settings/fraud-protection/advanced-settings/cards/purchase-price-threshold.tsx @@ -1,21 +1,14 @@ /** * External dependencies */ -import React, { - useContext, - useEffect, - useState, - useMemo, - SetStateAction, - Dispatch, -} from 'react'; +import React, { useContext, useMemo, SetStateAction, Dispatch } from 'react'; import { __ } from '@wordpress/i18n'; import AmountInput from 'wcpay/components/amount-input'; /** * Internal dependencies */ -import { getCurrency } from 'utils/currency'; +import { getCurrency } from 'multi-currency/interface/functions'; import FraudProtectionRuleCard from '../rule-card'; import FraudProtectionRuleToggle from '../rule-toggle'; import FraudProtectionRuleDescription from '../rule-description'; @@ -55,7 +48,6 @@ const PurchasePriceThresholdCustomForm: React.FC< PurchasePriceThresholdCustomFo const { protectionSettingsUI, setProtectionSettingsUI, - setProtectionSettingsChanged, setIsDirty, } = useContext( FraudPreventionSettingsContext ); @@ -67,25 +59,8 @@ const PurchasePriceThresholdCustomForm: React.FC< PurchasePriceThresholdCustomFo [ protectionSettingsUI, setting ] ); - const minAmountTemp = parseFloat( settingUI.min_amount + '' ); - const maxAmountTemp = parseFloat( settingUI.max_amount + '' ); - - const [ minAmount, setMinAmount ] = useState( minAmountTemp ?? '' ); - const [ maxAmount, setMaxAmount ] = useState( maxAmountTemp ?? '' ); - - useEffect( () => { - settingUI.min_amount = minAmount ? parseFloat( minAmount + '' ) : null; - settingUI.max_amount = maxAmount ? parseFloat( maxAmount + '' ) : null; - setProtectionSettingsUI( protectionSettingsUI ); - setProtectionSettingsChanged( ( prev ) => ! prev ); - }, [ - minAmount, - maxAmount, - protectionSettingsUI, - setProtectionSettingsUI, - setProtectionSettingsChanged, - settingUI, - ] ); + const minAmount = parseFloat( settingUI.min_amount + '' ); + const maxAmount = parseFloat( settingUI.max_amount + '' ); const areInputsEmpty = ! getFloatValue( minAmount + '' ) && ! getFloatValue( maxAmount + '' ); @@ -96,6 +71,17 @@ const PurchasePriceThresholdCustomForm: React.FC< PurchasePriceThresholdCustomFo const currencySymbol = getCurrencySymbol(); + const handleAmountInputChange = ( name: string ) => ( val: string ) => { + setProtectionSettingsUI( ( settings ) => ( { + ...settings, + [ setting ]: { + ...settings[ setting ], + [ name ]: val ? parseFloat( val + '' ) : null, + }, + } ) ); + setIsDirty( true ); + }; + return (
    Limits @@ -112,10 +98,7 @@ const PurchasePriceThresholdCustomForm: React.FC< PurchasePriceThresholdCustomFo prefix={ currencySymbol } placeholder={ '0.00' } value={ minAmount.toString() } - onChange={ ( val ) => { - setMinAmount( Number( val ) ); - setIsDirty( true ); - } } + onChange={ handleAmountInputChange( 'min_amount' ) } help={ __( 'Leave blank for no limit', 'woocommerce-payments' @@ -134,10 +117,7 @@ const PurchasePriceThresholdCustomForm: React.FC< PurchasePriceThresholdCustomFo prefix={ currencySymbol } placeholder={ '0.00' } value={ maxAmount.toString() } - onChange={ ( val ) => { - setMaxAmount( Number( val ) ); - setIsDirty( true ); - } } + onChange={ handleAmountInputChange( 'max_amount' ) } help={ __( 'Leave blank for no limit', 'woocommerce-payments' diff --git a/client/settings/fraud-protection/advanced-settings/cards/test/__snapshots__/address-mismatch.test.tsx.snap b/client/settings/fraud-protection/advanced-settings/cards/test/__snapshots__/address-mismatch.test.tsx.snap index ce9560f5875..566772c05f0 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/test/__snapshots__/address-mismatch.test.tsx.snap +++ b/client/settings/fraud-protection/advanced-settings/cards/test/__snapshots__/address-mismatch.test.tsx.snap @@ -158,6 +158,7 @@ exports[`Address mismatch card renders correctly when enabled 1`] = ` > - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States @@ -232,6 +233,7 @@ exports[`International IP address card renders correctly when enabled and checke > - Orders from the following countries will be blocked by the filter: + Orders from the following countries will be screened by the filter: Canada, United States @@ -753,7 +755,7 @@ exports[`International IP address card renders correctly when woocommerce_allowe data-wp-c16t="true" data-wp-component="FlexItem" > - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States diff --git a/client/settings/fraud-protection/advanced-settings/cards/test/__snapshots__/ip-address-mismatch.test.tsx.snap b/client/settings/fraud-protection/advanced-settings/cards/test/__snapshots__/ip-address-mismatch.test.tsx.snap index 30b97d21b1a..f5f48430b26 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/test/__snapshots__/ip-address-mismatch.test.tsx.snap +++ b/client/settings/fraud-protection/advanced-settings/cards/test/__snapshots__/ip-address-mismatch.test.tsx.snap @@ -174,6 +174,7 @@ exports[`International billing address card renders correctly when enabled 1`] = > { const contextValue = { protectionSettingsUI: settings, setProtectionSettingsUI: setSettings, - protectionSettingsChanged: false, - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; test( 'renders correctly', () => { diff --git a/client/settings/fraud-protection/advanced-settings/cards/test/avs-mismatch.test.tsx b/client/settings/fraud-protection/advanced-settings/cards/test/avs-mismatch.test.tsx index b2ae2de8e27..c178672128d 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/test/avs-mismatch.test.tsx +++ b/client/settings/fraud-protection/advanced-settings/cards/test/avs-mismatch.test.tsx @@ -40,8 +40,6 @@ describe( 'AVS mismatch card', () => { const contextValue = { protectionSettingsUI: settings, setProtectionSettingsUI: setSettings, - protectionSettingsChanged: false, - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; const { container } = render( @@ -69,8 +67,6 @@ describe( 'AVS mismatch card', () => { const contextValue = { protectionSettingsUI: settings, setProtectionSettingsUI: setSettings, - protectionSettingsChanged: false, - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; const { container } = render( diff --git a/client/settings/fraud-protection/advanced-settings/cards/test/cvc-verification.test.tsx b/client/settings/fraud-protection/advanced-settings/cards/test/cvc-verification.test.tsx index dfbbbc47ad5..9be801f735b 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/test/cvc-verification.test.tsx +++ b/client/settings/fraud-protection/advanced-settings/cards/test/cvc-verification.test.tsx @@ -40,8 +40,6 @@ describe( 'CVC verification card', () => { const contextValue = { protectionSettingsUI: settings, setProtectionSettingsUI: setSettings, - protectionSettingsChanged: false, - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; const { container } = render( @@ -72,8 +70,6 @@ describe( 'CVC verification card', () => { const contextValue = { protectionSettingsUI: settings, setProtectionSettingsUI: setSettings, - protectionSettingsChanged: false, - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; const { container } = render( diff --git a/client/settings/fraud-protection/advanced-settings/cards/test/international-ip-address.test.tsx b/client/settings/fraud-protection/advanced-settings/cards/test/international-ip-address.test.tsx index 6a36f94b4ee..a8a2a699190 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/test/international-ip-address.test.tsx +++ b/client/settings/fraud-protection/advanced-settings/cards/test/international-ip-address.test.tsx @@ -41,8 +41,6 @@ describe( 'International IP address card', () => { const contextValue = { protectionSettingsUI: settings, setProtectionSettingsUI: setSettings, - protectionSettingsChanged: false, - setProtectionSettingsChanged: jest.fn(), isDirty: false, setIsDirty: jest.fn(), }; diff --git a/client/settings/fraud-protection/advanced-settings/cards/test/ip-address-mismatch.test.tsx b/client/settings/fraud-protection/advanced-settings/cards/test/ip-address-mismatch.test.tsx index b102364ad75..f2eaa32ba8c 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/test/ip-address-mismatch.test.tsx +++ b/client/settings/fraud-protection/advanced-settings/cards/test/ip-address-mismatch.test.tsx @@ -38,8 +38,6 @@ describe( 'International billing address card', () => { const contextValue = { protectionSettingsUI: settings, setProtectionSettingsUI: setSettings, - protectionSettingsChanged: false, - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; global.wcSettings = { diff --git a/client/settings/fraud-protection/advanced-settings/cards/test/order-items-threshold.test.tsx b/client/settings/fraud-protection/advanced-settings/cards/test/order-items-threshold.test.tsx index 268845ba776..b2832aea03c 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/test/order-items-threshold.test.tsx +++ b/client/settings/fraud-protection/advanced-settings/cards/test/order-items-threshold.test.tsx @@ -37,8 +37,6 @@ describe( 'Order items threshold card', () => { const contextValue = { protectionSettingsUI: settings, setProtectionSettingsUI: setSettings, - protectionSettingsChanged: false, - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; test( 'renders correctly', () => { diff --git a/client/settings/fraud-protection/advanced-settings/cards/test/purchase-price-threshold.test.tsx b/client/settings/fraud-protection/advanced-settings/cards/test/purchase-price-threshold.test.tsx index 23f12a04d51..163cb3d06b8 100644 --- a/client/settings/fraud-protection/advanced-settings/cards/test/purchase-price-threshold.test.tsx +++ b/client/settings/fraud-protection/advanced-settings/cards/test/purchase-price-threshold.test.tsx @@ -65,8 +65,6 @@ describe( 'Purchase price threshold card', () => { const contextValue = { protectionSettingsUI: settings, setProtectionSettingsUI: setSettings, - protectionSettingsChanged: false, - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; test( 'renders correctly', () => { diff --git a/client/settings/fraud-protection/advanced-settings/context.ts b/client/settings/fraud-protection/advanced-settings/context.ts index aa708fa36d0..c46b6bad440 100644 --- a/client/settings/fraud-protection/advanced-settings/context.ts +++ b/client/settings/fraud-protection/advanced-settings/context.ts @@ -7,8 +7,6 @@ import { FraudPreventionSettingsContextType } from '../interfaces'; const FraudPreventionSettingsContext = createContext( { protectionSettingsUI: {}, setProtectionSettingsUI: () => null, - protectionSettingsChanged: false, - setProtectionSettingsChanged: () => false, setIsDirty: () => null, } as FraudPreventionSettingsContextType ); diff --git a/client/settings/fraud-protection/advanced-settings/index.tsx b/client/settings/fraud-protection/advanced-settings/index.tsx index 881a09fdb90..74a37e9734a 100644 --- a/client/settings/fraud-protection/advanced-settings/index.tsx +++ b/client/settings/fraud-protection/advanced-settings/index.tsx @@ -122,10 +122,6 @@ const FraudProtectionAdvancedSettingsPage: React.FC = () => { const [ protectionSettingsUI, setProtectionSettingsUI ] = useState< ProtectionSettingsUI >( {} ); - const [ - protectionSettingsChanged, - setProtectionSettingsChanged, - ] = useState( false ); useEffect( () => { setProtectionSettingsUI( @@ -317,7 +313,7 @@ const FraudProtectionAdvancedSettingsPage: React.FC = () => { useEffect( confirmLeaveCallback, [ confirmLeaveCallback, - protectionSettingsChanged, + protectionSettingsUI, advancedFraudProtectionSettings, ] ); @@ -342,8 +338,6 @@ const FraudProtectionAdvancedSettingsPage: React.FC = () => { value={ { protectionSettingsUI, setProtectionSettingsUI, - protectionSettingsChanged, - setProtectionSettingsChanged, setIsDirty, } } > diff --git a/client/settings/fraud-protection/advanced-settings/rule-toggle.tsx b/client/settings/fraud-protection/advanced-settings/rule-toggle.tsx index 85e32790595..c2c49da2f5f 100644 --- a/client/settings/fraud-protection/advanced-settings/rule-toggle.tsx +++ b/client/settings/fraud-protection/advanced-settings/rule-toggle.tsx @@ -1,7 +1,7 @@ /** * External dependencies */ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext } from 'react'; import { __ } from '@wordpress/i18n'; import { ToggleControl, RadioControl } from '@wordpress/components'; @@ -10,6 +10,7 @@ import { ToggleControl, RadioControl } from '@wordpress/components'; */ import './../style.scss'; import FraudPreventionSettingsContext from './context'; +import { FraudPreventionSettings } from '../interfaces'; interface FraudProtectionRuleToggleProps { setting: string; @@ -49,6 +50,15 @@ export const getHelpText = ( return helpTextMapping[ filterAction ]; }; +const getFilterAction = ( + settingUI: FraudPreventionSettings, + isFRTReviewFeatureActive: boolean +) => { + if ( ! isFRTReviewFeatureActive ) return filterActions.BLOCK; + + return settingUI.block ? filterActions.BLOCK : filterActions.REVIEW; +}; + const FraudProtectionRuleToggle: React.FC< FraudProtectionRuleToggleProps > = ( { setting, label, @@ -57,51 +67,31 @@ const FraudProtectionRuleToggle: React.FC< FraudProtectionRuleToggleProps > = ( const { protectionSettingsUI, setProtectionSettingsUI, - setProtectionSettingsChanged, setIsDirty, } = useContext( FraudPreventionSettingsContext ); const { isFRTReviewFeatureActive } = wcpaySettings; - const [ toggleState, setToggleState ] = useState( false ); - const [ filterAction, setFilterAction ] = useState( - isFRTReviewFeatureActive ? filterActions.REVIEW : filterActions.BLOCK - ); - const settingUI = protectionSettingsUI?.[ setting ]; + const filterAction = getFilterAction( settingUI, isFRTReviewFeatureActive ); + + const handleToggleChange = ( field: string, value: boolean ) => { + setProtectionSettingsUI( ( settings ) => ( { + ...settings, + [ setting ]: { + ...settings[ setting ], + [ field ]: value, + }, + } ) ); + setIsDirty( true ); + }; - // Set initial states from saved settings. - useEffect( () => { - if ( ! settingUI ) return; - - setToggleState( settingUI.enabled ); - setFilterAction( () => { - if ( ! isFRTReviewFeatureActive ) return filterActions.BLOCK; - - return settingUI.block ? filterActions.BLOCK : filterActions.REVIEW; - } ); - }, [ settingUI, isFRTReviewFeatureActive ] ); - - // Set global object values from input changes. - useEffect( () => { - if ( ! settingUI ) return; - - settingUI.enabled = toggleState; - settingUI.block = filterActions.BLOCK === filterAction; - setProtectionSettingsUI( protectionSettingsUI ); - setProtectionSettingsChanged( ( prev ) => ! prev ); - }, [ - settingUI, - toggleState, - filterAction, - setProtectionSettingsChanged, - protectionSettingsUI, - setProtectionSettingsUI, - ] ); + const handleEnableToggleChange = ( value: boolean ) => { + handleToggleChange( 'enabled', value ); + }; - const handleToggleChange = () => { - setToggleState( ( value ) => ! value ); - setIsDirty( true ); + const handleBlockToggleChange = ( value: string ) => { + handleToggleChange( 'block', filterActions.BLOCK === value ); }; if ( ! protectionSettingsUI ) { @@ -117,13 +107,13 @@ const FraudProtectionRuleToggle: React.FC< FraudProtectionRuleToggleProps > = ( - { toggleState && ( + { settingUI?.enabled && (
    { children } @@ -139,7 +129,7 @@ const FraudProtectionRuleToggle: React.FC< FraudProtectionRuleToggleProps > = (
    ) } diff --git a/client/settings/fraud-protection/advanced-settings/test/__snapshots__/index.test.tsx.snap b/client/settings/fraud-protection/advanced-settings/test/__snapshots__/index.test.tsx.snap index dddbf129bdb..c550c6f6480 100644 --- a/client/settings/fraud-protection/advanced-settings/test/__snapshots__/index.test.tsx.snap +++ b/client/settings/fraud-protection/advanced-settings/test/__snapshots__/index.test.tsx.snap @@ -340,7 +340,7 @@ exports[`Advanced fraud protection settings doesn't save when there's a validati data-wp-c16t="true" data-wp-component="FlexItem" > - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States @@ -1345,7 +1345,7 @@ exports[`Advanced fraud protection settings doesn't save when there's a validati data-wp-c16t="true" data-wp-component="FlexItem" > - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States @@ -2119,7 +2119,7 @@ exports[`Advanced fraud protection settings renders an error message when settin id="a11y-speak-polite" style="position: absolute;margin: -1px;padding: 0;height: 1px;width: 1px;overflow: hidden;clip: rect(1px, 1px, 1px, 1px);-webkit-clip-path: inset(50%);clip-path: inset(50%);border: 0;word-wrap: normal !important;" > - Orders from outside of the following countries will be blocked by the filter: Canada, United States + For security, this filter is enabled and cannot be modified. Payments failing CVC verification will be blocked. Learn more
    @@ -2415,7 +2415,7 @@ exports[`Advanced fraud protection settings renders an error message when settin data-wp-c16t="true" data-wp-component="FlexItem" > - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States @@ -3277,7 +3277,7 @@ exports[`Advanced fraud protection settings renders an error message when settin data-wp-c16t="true" data-wp-component="FlexItem" > - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States @@ -3925,7 +3925,7 @@ exports[`Advanced fraud protection settings renders correctly 1`] = ` id="a11y-speak-polite" style="position: absolute;margin: -1px;padding: 0;height: 1px;width: 1px;overflow: hidden;clip: rect(1px, 1px, 1px, 1px);-webkit-clip-path: inset(50%);clip-path: inset(50%);border: 0;word-wrap: normal !important;" > - Orders from outside of the following countries will be blocked by the filter: Canada, United States + For security, this filter is enabled and cannot be modified. Payments failing CVC verification will be blocked. Learn more
    - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States @@ -5012,7 +5012,7 @@ exports[`Advanced fraud protection settings renders correctly 1`] = ` data-wp-c16t="true" data-wp-component="FlexItem" > - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States @@ -5659,7 +5659,7 @@ exports[`Advanced fraud protection settings saves settings when there are no val id="a11y-speak-polite" style="position: absolute;margin: -1px;padding: 0;height: 1px;width: 1px;overflow: hidden;clip: rect(1px, 1px, 1px, 1px);-webkit-clip-path: inset(50%);clip-path: inset(50%);border: 0;word-wrap: normal !important;" > - Orders from outside of the following countries will be blocked by the filter: Canada, United States + For security, this filter is enabled and cannot be modified. Payments failing CVC verification will be blocked. Learn more
    @@ -5938,7 +5938,7 @@ exports[`Advanced fraud protection settings saves settings when there are no val data-wp-c16t="true" data-wp-component="FlexItem" > - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States @@ -6863,7 +6863,7 @@ exports[`Advanced fraud protection settings saves settings when there are no val data-wp-c16t="true" data-wp-component="FlexItem" > - Orders from outside of the following countries will be blocked by the filter: + Orders from outside of the following countries will be screened by the filter: Canada, United States diff --git a/client/settings/fraud-protection/advanced-settings/test/__snapshots__/rule-toggle.test.tsx.snap b/client/settings/fraud-protection/advanced-settings/test/__snapshots__/rule-toggle.test.tsx.snap index daa0f6c642e..daa15a8d239 100644 --- a/client/settings/fraud-protection/advanced-settings/test/__snapshots__/rule-toggle.test.tsx.snap +++ b/client/settings/fraud-protection/advanced-settings/test/__snapshots__/rule-toggle.test.tsx.snap @@ -219,6 +219,7 @@ exports[`Fraud protection rule toggle tests renders correctly when enabled 1`] = > { block: false, }, }, - protectionSettingsChanged: false, setProtectionSettingsUI: jest.fn(), - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; @@ -55,9 +52,7 @@ describe( 'Fraud protection rule toggle tests', () => { block: false, }, }, - protectionSettingsChanged: false, setProtectionSettingsUI: jest.fn(), - setProtectionSettingsChanged: jest.fn(), setIsDirty: jest.fn(), }; } ); @@ -134,7 +129,9 @@ describe( 'Fraud protection rule toggle tests', () => { expect( container.getByLabelText( 'Test rule toggle' ) ).toBeChecked(); expect( container.queryByText( 'test content' ) ).toBeInTheDocument(); } ); - test( 'sets the value correctly when enabled', () => { + test( 'calls the toggle enable function when clicking in the label', () => { + mockContext.protectionSettingsUI.test_rule.enabled = false; + const container = render( { ); + const activationToggle = container.getByLabelText( 'Test rule toggle' ); - expect( - mockContext.protectionSettingsUI.test_rule.enabled - ).toBeFalsy(); - activationToggle.click(); - expect( - mockContext.protectionSettingsUI.test_rule.enabled - ).toBeTruthy(); - activationToggle.click(); - expect( - mockContext.protectionSettingsUI.test_rule.enabled - ).toBeFalsy(); + userEvent.click( activationToggle ); + + expect( mockContext.setProtectionSettingsUI ).toHaveBeenCalled(); } ); } ); diff --git a/client/settings/fraud-protection/interfaces.ts b/client/settings/fraud-protection/interfaces.ts index 7ad040bad87..a034fb5d6a5 100644 --- a/client/settings/fraud-protection/interfaces.ts +++ b/client/settings/fraud-protection/interfaces.ts @@ -33,9 +33,7 @@ export type ProtectionSettingsUI = Record< string, FraudPreventionSettings >; export interface FraudPreventionSettingsContextType { protectionSettingsUI: ProtectionSettingsUI; - setProtectionSettingsUI: ( settings: ProtectionSettingsUI ) => void; - protectionSettingsChanged: boolean; - setProtectionSettingsChanged: Dispatch< SetStateAction< boolean > >; + setProtectionSettingsUI: Dispatch< SetStateAction< ProtectionSettingsUI > >; setIsDirty: Dispatch< SetStateAction< boolean > >; } diff --git a/client/settings/fraud-protection/test/index.test.tsx b/client/settings/fraud-protection/test/index.test.tsx index 0719a904c78..1b78011aad4 100644 --- a/client/settings/fraud-protection/test/index.test.tsx +++ b/client/settings/fraud-protection/test/index.test.tsx @@ -11,7 +11,6 @@ import { useDispatch } from '@wordpress/data'; import FraudProtection from '..'; import { useCurrentProtectionLevel, - useCurrencies, useAdvancedFraudProtectionSettings, useSettings, } from 'wcpay/data'; @@ -29,7 +28,6 @@ jest.mock( 'wcpay/data', () => ( { useAdvancedFraudProtectionSettings: jest.fn(), useCurrentProtectionLevel: jest.fn(), useSettings: jest.fn(), - useCurrencies: jest.fn(), } ) ); jest.mock( '@wordpress/data', () => ( { @@ -44,10 +42,6 @@ const mockUseCurrentProtectionLevel = useCurrentProtectionLevel as jest.MockedFu () => [ string, ( level: string ) => void ] >; -const mockUseCurrencies = useCurrencies as jest.MockedFunction< - () => { currencies: Record< string, any >; isLoading: boolean } ->; - const mockUseAdvancedFraudProtectionSettings = useAdvancedFraudProtectionSettings as jest.MockedFunction< () => [ any[] | string, ( settings: string ) => void ] >; @@ -70,16 +64,6 @@ describe( 'FraudProtection', () => { 'standard', jest.fn(), ] ); - mockUseCurrencies.mockReturnValue( { - isLoading: false, - currencies: { - available: { - EUR: { name: 'Euro', symbol: '€' }, - USD: { name: 'US Dollar', symbol: '$' }, - PLN: { name: 'Polish złoty', symbol: 'zł' }, - }, - }, - } ); mockUseAdvancedFraudProtectionSettings.mockReturnValue( [ [], diff --git a/client/settings/payment-methods-list/index.js b/client/settings/payment-methods-list/index.js index 99a34b40daf..997c2bb9874 100644 --- a/client/settings/payment-methods-list/index.js +++ b/client/settings/payment-methods-list/index.js @@ -22,7 +22,7 @@ import { upeCapabilityStatuses } from 'wcpay/additional-methods-setup/constants' import ConfirmPaymentMethodActivationModal from './activation-modal'; import ConfirmPaymentMethodDeleteModal from './delete-modal'; import CapabilityRequestNotice from './capability-request'; -import { getMissingCurrenciesTooltipMessage } from 'wcpay/multi-currency/missing-currencies-message'; +import { getMissingCurrenciesTooltipMessage } from 'multi-currency/interface/functions'; const PaymentMethodsList = ( { methodIds } ) => { const [ enabledMethodIds ] = useEnabledPaymentMethodIds(); diff --git a/client/settings/payment-methods-section/__tests__/payment-methods-section.test.js b/client/settings/payment-methods-section/__tests__/payment-methods-section.test.js index 2e1f1da1538..d64f2ded639 100644 --- a/client/settings/payment-methods-section/__tests__/payment-methods-section.test.js +++ b/client/settings/payment-methods-section/__tests__/payment-methods-section.test.js @@ -35,8 +35,6 @@ jest.mock( '@woocommerce/components', () => { jest.mock( 'wcpay/data', () => ( { useEnabledPaymentMethodIds: jest.fn(), useGetAvailablePaymentMethodIds: jest.fn(), - useCurrencies: jest.fn().mockReturnValue( { isLoading: true } ), - useEnabledCurrencies: jest.fn().mockReturnValue( {} ), useGetPaymentMethodStatuses: jest.fn().mockReturnValue( {} ), useManualCapture: jest.fn(), useSelectedPaymentMethod: jest.fn(), @@ -45,6 +43,16 @@ jest.mock( 'wcpay/data', () => ( { useSettings: jest.fn().mockReturnValue( { isLoading: false } ), } ) ); +jest.mock( 'multi-currency/interface/data', () => ( { + useCurrencies: jest.fn().mockReturnValue( { isLoading: true } ), + useEnabledCurrencies: jest.fn().mockReturnValue( {} ), +} ) ); + +jest.mock( 'multi-currency/interface/data', () => ( { + useCurrencies: jest.fn().mockReturnValue( { isLoading: true } ), + useEnabledCurrencies: jest.fn().mockReturnValue( {} ), +} ) ); + jest.mock( '@wordpress/data', () => ( { useDispatch: jest .fn() diff --git a/client/settings/settings-manager/index.js b/client/settings/settings-manager/index.js index 2668afa04c5..fc238c706b2 100644 --- a/client/settings/settings-manager/index.js +++ b/client/settings/settings-manager/index.js @@ -84,17 +84,17 @@ const DepositsDescription = () => { return ( <> -

    { __( 'Deposits', 'woocommerce-payments' ) }

    +

    { __( 'Payouts', 'woocommerce-payments' ) }

    { sprintf( __( - 'Funds are available for deposit %s business days after they’re received.', + 'Funds are available for payout %s business days after they’re received.', 'woocommerce-payments' ), depositDelayDays ) }

    - + { __( 'Learn more about pending schedules', 'woocommerce-payments' @@ -242,7 +242,7 @@ const SettingsManager = () => { -
    +
    diff --git a/client/style.scss b/client/style.scss index 7fe3269109f..2e4b8312271 100644 --- a/client/style.scss +++ b/client/style.scss @@ -20,15 +20,10 @@ } } -.woocommerce-table { - font-weight: 300; - letter-spacing: 0.012rem; - color: $studio-gray-60; - - .woocommerce-table__summary { - border-radius: 0 0 3px 3px; - } - +/** +* This styling is for all `` components found in WooPayments screens. +*/ +.woocommerce-payments-page .woocommerce-table { .woocommerce-table__item { white-space: nowrap; } diff --git a/client/tokenized-payment-request/blocks/index.js b/client/tokenized-payment-request/blocks/index.js index ce68e13ceca..ebca67f1b7d 100644 --- a/client/tokenized-payment-request/blocks/index.js +++ b/client/tokenized-payment-request/blocks/index.js @@ -19,7 +19,10 @@ const ApplePayPreview = () => ; const tokenizedCartPaymentRequestPaymentMethod = ( api ) => ( { name: PAYMENT_METHOD_NAME_PAYMENT_REQUEST, content: ( - + ), edit: , canMakePayment: ( cartData ) => { @@ -40,7 +43,7 @@ const tokenizedCartPaymentRequestPaymentMethod = ( api ) => ( { return false; } - return api.loadStripe( true ).then( ( stripe ) => { + return api.loadStripeForExpressCheckout().then( ( stripe ) => { // Create a payment request and check if we can make a payment to determine whether to // show the Payment Request Button or not. This is necessary because a browser might be // able to load the Stripe JS object, but not support Payment Requests. diff --git a/client/tos/modal/index.js b/client/tos/modal/index.js index 5b5766e877c..7e92acc5fdc 100644 --- a/client/tos/modal/index.js +++ b/client/tos/modal/index.js @@ -102,7 +102,7 @@ const DisableModalUI = ( { onDisable, onCancel, isBusy, hasError } ) => { __( 'By declining our {{link}}Terms of Service{{/link}},' + ' you’ll no longer be able to capture credit card payments using %s.' + - ' Your previous transaction and deposit data will still be available.', + ' Your previous transaction and payout data will still be available.', 'woocommerce-payments' ), 'WooPayments' diff --git a/client/tos/modal/test/__snapshots__/index.js.snap b/client/tos/modal/test/__snapshots__/index.js.snap index 27887ceeb22..f89df7e8b64 100644 --- a/client/tos/modal/test/__snapshots__/index.js.snap +++ b/client/tos/modal/test/__snapshots__/index.js.snap @@ -103,7 +103,7 @@ exports[`ToS modal should render disable plugin modal on decline 1`] = ` > Terms of Service - , you’ll no longer be able to capture credit card payments using WooPayments. Your previous transaction and deposit data will still be available. + , you’ll no longer be able to capture credit card payments using WooPayments. Your previous transaction and payout data will still be available.