diff --git a/.eslintrc b/.eslintrc index 6d23537432e..4b37af1e0ff 100644 --- a/.eslintrc +++ b/.eslintrc @@ -102,10 +102,6 @@ { "selector": "ImportDeclaration[source.value=/gridicons(?!\\u002F)/]", "message": "Do not import whole Gridicons, import them individually with 'gridicons/dist/icon-name'." - }, - { - "selector": "ImportDeclaration[source.value='@wordpress/components']", - "message": "Do not import from '@wordpress/components' directly. Use components from 'wcpay/components/wp-components-wrapped' instead." } ] }, diff --git a/.github/workflows/build-live-branch.yml b/.github/workflows/build-live-branch.yml new file mode 100644 index 00000000000..81393af1c3e --- /dev/null +++ b/.github/workflows/build-live-branch.yml @@ -0,0 +1,119 @@ +name: Build live branch when develop updated +on: + workflow_dispatch: + push: + branches: + - develop + paths-ignore: + - '.cursor/**' + - '.github/**' + - '!.github/workflows/build-live-branch.yml' + - '.husky/**' + - '.bin/**' + - 'docker/**' + - 'docs/**' + - 'tasks/**' + - 'tests/**' + - '**/tests/**' + - 'wordpress-org-assets/**' + - '**/changelog/**' + - '**/changelog.txt' + - '**/readme.txt' + - '.gitignore' + - 'CODEOWNERS' + - '**/*.md' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + build: + if: github.repository_owner == 'automattic' && github.actor != 'github-actions[bot]' + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: "Checkout repository" + uses: actions/checkout@v4 + + - name: "Set up repository" + uses: ./.github/actions/setup-repo + + - name: "Get current version" + id: current-version + run: | + VERSION=$(jq '.version' package.json -r) + echo "Current version found: $VERSION" >> $GITHUB_STEP_SUMMARY + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + + - name: "Get dev version" + id: get-dev-version + env: + CURRENT_VERSION: ${{ steps.current-version.outputs.VERSION }} + run: | + DEV_SUFFIX_VERSION="${GITHUB_RUN_ID}-g$(git rev-parse --short HEAD)" + DEV_VERSION="${CURRENT_VERSION}-${DEV_SUFFIX_VERSION}" + echo "Dev Version: $DEV_VERSION" >> $GITHUB_STEP_SUMMARY + echo "DEV_VERSION=$DEV_VERSION" >> $GITHUB_OUTPUT + + - name: "Bump dev version" + id: bump-dev-version + env: + DEV_VERSION: ${{ steps.get-dev-version.outputs.DEV_VERSION }} + run: | + # 'Version' header in woocommerce-payments.php + sed -i "s/^ \* Version: .*$/ * Version: $DEV_VERSION/" woocommerce-payments.php + + # 'version' field in package.json + sed -ri 's/("version": )".*"/\1"'${DEV_VERSION}'"/' package.json + + # 'Stable tag' header in readme.txt; + sed -i "s/^Stable tag: .*$/Stable tag: $DEV_VERSION/" readme.txt + + - name: "Build the plugin" + id: build_plugin + uses: ./.github/actions/build + + - name: "Update the structure of artifacts for Jetpack Beta Builder" + run: | + cd release + mv woocommerce-payments woocommerce-payments-dev + zip -q -r "woocommerce-payments-dev.zip" "woocommerce-payments-dev/" + rm -fR "woocommerce-payments-dev" + + - name: "Get plugin data for Jetpack Beta Builder" + id: get-plugin-data + env: + DEV_VERSION: ${{ steps.get-dev-version.outputs.DEV_VERSION }} + run: | + # Plugin data is passed as a JSON object. + PLUGIN_DATA="{}" + PLUGIN_DATA=$( jq -c --arg slug "woocommerce-payments" --arg ver "$DEV_VERSION" '.[ $slug ] = { version: $ver }' <<<"$PLUGIN_DATA" ) + echo "plugin-data=$PLUGIN_DATA" >> $GITHUB_OUTPUT + + - name: "Upload the zip file as an artifact" + uses: actions/upload-artifact@v4 + if: steps.get-plugin-data.outputs.plugin-data != '{}' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + name: plugins + path: release + # Only need to retain for a day since the beta builder slurps it up to distribute. + retention-days: 1 + + - name: "Inform Jetpack Beta Builder webhook" + if: steps.get-plugin-data.outputs.plugin-data != '{}' + env: + SECRET: ${{ secrets.WCPAYBETA_SECRET }} + PLUGIN_DATA: ${{ steps.get-plugin-data.outputs.plugin-data }} + run: | + curl -v --fail -L \ + --url "https://betadownload.jetpack.me/gh-action.php?run_id=$GITHUB_RUN_ID&commit=$GITHUB_SHA" \ + --form-string "repo=$GITHUB_REPOSITORY" \ + --form-string "branch=${GITHUB_REF#refs/heads/}" \ + --form-string "plugins=$PLUGIN_DATA" \ + --form-string "secret=$SECRET" diff --git a/.github/workflows/e2e-pull-request.yml b/.github/workflows/e2e-pull-request.yml index e1ad0802238..75080631e7e 100644 --- a/.github/workflows/e2e-pull-request.yml +++ b/.github/workflows/e2e-pull-request.yml @@ -47,14 +47,15 @@ jobs: strategy: fail-fast: false matrix: + wc_version: [ 'latest' ] test_groups: [ 'wcpay', 'subscriptions' ] # [TODO] Unskip blocks tests after investigating constant failures. test_branches: [ 'merchant', 'shopper' ] - name: WC - latest | ${{ matrix.test_groups }} - ${{ matrix.test_branches }} + name: WC - ${{ matrix.wc_version }} | ${{ matrix.test_groups }} - ${{ matrix.test_branches }} env: E2E_WP_VERSION: 'latest' - E2E_WC_VERSION: 'latest' + E2E_WC_VERSION: ${{ matrix.wc_version }} E2E_GROUP: ${{ matrix.test_groups }} E2E_BRANCH: ${{ matrix.test_branches }} diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index a7dd0b53bb9..9dac946779f 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -37,7 +37,7 @@ jobs: - name: "Generate matrix" id: generate_matrix run: | - WC_VERSIONS=$( echo "[\"7.7.0\", \"latest\", \"beta\"]" ) + WC_VERSIONS=$( echo "[\"7.7.0\", \"latest\", \"beta\", \"rc\"]" ) echo "matrix={\"woocommerce\":$WC_VERSIONS,\"test_groups\":[\"wcpay\", \"subscriptions\"],\"test_branches\":[\"merchant\", \"shopper\"]}" >> $GITHUB_OUTPUT # Run WCPay & subscriptions tests against specific WC versions diff --git a/.github/workflows/release-code-freeze.yml b/.github/workflows/release-code-freeze.yml index 8e3482c6556..24e2eb6cffc 100644 --- a/.github/workflows/release-code-freeze.yml +++ b/.github/workflows/release-code-freeze.yml @@ -2,8 +2,8 @@ name: "Release - Code freeze" # This action will run according to the cron schedule or when triggered manually on: - schedule: - - cron: '0 12 * * 0' # Run at 1200 UTC on Sundays. + # schedule: + # - cron: '0 18 * * 3' # Run at 1800 UTC on Wednesdays. workflow_dispatch: inputs: skipSlackPing: @@ -57,16 +57,16 @@ jobs: env: NEXT_VERSION: ${{ steps.next-version.outputs.NEXT_RELEASE_VERSION }} run: | - git fetch --tags origin - NEXT_VERSION_TAG_STABLE=$(git tag -l "${{ env.NEXT_VERSION }}" | tail -1) - NEXT_VERSION_TAG_FROM_WEEK_2=$(git tag -l "${{ env.NEXT_VERSION }}-test-2" | tail -1) - if [[ -z "$NEXT_VERSION_TAG_FROM_WEEK_2" ]]; then - echo "Code freeze is not needed :x:" >> $GITHUB_STEP_SUMMARY - echo "FREEZE=0" >> $GITHUB_OUTPUT - elif [[ -z "$NEXT_VERSION_TAG_STABLE" ]]; then - echo "Code freeze is needed :white_check_mark:" >> $GITHUB_STEP_SUMMARY - echo "FREEZE=1" >> $GITHUB_OUTPUT - fi + # git fetch --tags origin + # NEXT_VERSION_TAG_STABLE=$(git tag -l "${{ env.NEXT_VERSION }}" | tail -1) + # NEXT_VERSION_TAG_FROM_WEEK_2=$(git tag -l "${{ env.NEXT_VERSION }}-test-2" | tail -1) + # if [[ -z "$NEXT_VERSION_TAG_FROM_WEEK_2" ]]; then + # echo "Code freeze is not needed :x:" >> $GITHUB_STEP_SUMMARY + # echo "FREEZE=0" >> $GITHUB_OUTPUT + # elif [[ -z "$NEXT_VERSION_TAG_STABLE" ]]; then + # fi + echo "Code freeze is needed :white_check_mark:" >> $GITHUB_STEP_SUMMARY + echo "FREEZE=1" >> $GITHUB_OUTPUT create-release-pr: name: "Raise a PR to trunk" diff --git a/assets/css/admin.rtl.css b/assets/css/admin.rtl.css index 0691ba264a0..9ebeb98d5bc 100644 --- a/assets/css/admin.rtl.css +++ b/assets/css/admin.rtl.css @@ -131,6 +131,14 @@ background-image: url( '../images/payment-methods/afterpay-icon.svg' ); } +.payment-method__brand--afterpay_clearpay.account-country--gb { + background-image: url( '../images/payment-methods/clearpay.svg' ); +} + +.payment-method__brand--afterpay_clearpay.account-country--us { + background-image: url( '../images/payment-methods/afterpay-cashapp-icon.svg' ); +} + .payment-method__brand--affirm { background-image: url( '../images/payment-methods/affirm-icon.svg' ); } diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh index 907c10ebcc1..5e489384ee9 100755 --- a/bin/install-wp-tests.sh +++ b/bin/install-wp-tests.sh @@ -191,9 +191,9 @@ install_woocommerce() { WC_INSTALL_EXTRA='' INSTALLED_WC_VERSION=$(wp plugin get woocommerce --field=version) - if [[ $WC_VERSION == 'beta' ]]; then + if [[ $WC_VERSION == 'beta' ]] || [[ $WC_VERSION == 'rc' ]]; then # Get the latest non-trunk version number from the .org repo. This will usually be the latest release, beta, or rc. - WC_VERSION=$(curl https://api.wordpress.org/plugins/info/1.0/woocommerce.json | jq -r '.versions | with_entries(select(.key|match("beta";"i"))) | keys[-1]' --sort-keys) + WC_VERSION=$(curl https://api.wordpress.org/plugins/info/1.0/woocommerce.json | jq -r '.versions | with_entries(select(.key|match("'$WC_VERSION'";"i"))) | keys | sort_by( . | split("-")[0] | split(".") | map(tonumber) ) | last' --sort-keys) fi if [[ -n $INSTALLED_WC_VERSION ]] && [[ $WC_VERSION == 'latest' ]]; then diff --git a/changelog.txt b/changelog.txt index 02b7d128ceb..fe71322fdde 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,29 @@ *** WooPayments Changelog *** += 9.8.0 - 2025-08-13 = +* Add - Add address autocomplete to Checkout +* Add - Add support for small screens on the evidence submission form. +* Fix - Fix customer details section when name and/or email are very big. +* Fix - Fix Google/Apple Pay "State / County is required" error during checkout for Croatia +* Fix - Fix the icon border of the Steps component for a dispute. +* Fix - Reset the enabled payment methods to default value on account reset. +* Fix - Suppress sending completed-renewal-order email after dispute resolution +* Update - As of this change, we stop bundling WordPress Components in favor of using the wp.components available in the WordPress installation. +* Update - Make onboading pages use the pw.components available in the WordPress installation. +* Update - Make the connect acctount components use the wp.components from the installation. +* Update - Make the KYC onboarding use the WP components available in the installation. +* Update - update: ensure Google Pay/Apple Pay can check out w/ LT addresses +* Update - update: fraud protection rules to use WP components bundled within the WP installation +* Update - Update documents page to use WP components available in the WordPress installation. +* Update - Update loan page to use the installation WordPress components. +* Update - Update the "Learn more about disputes" link in the confirmation screen of the disputes documentation. +* Dev - Fix: enhances the robustness of the selectPaymentMethod method in end-to-end tests +* Dev - Fix: Respond to a dispute e2e tests +* Dev - Fix: select payment method shopper util +* Dev - Removed all the Progressive Onboarding (PO) code. +* Dev - update: use React 18 +* Dev - Update tested WooCommerce version to 10.1.0 + = 9.7.0 - 2025-07-24 = * Add - Add a confirmation screen to the new flow for submitting dispute evidence. * Add - Add Credit not processed logic for the new evidence submission form. diff --git a/client/capital/test/__snapshots__/index.test.tsx.snap b/client/capital/__tests__/__snapshots__/index.test.tsx.snap similarity index 100% rename from client/capital/test/__snapshots__/index.test.tsx.snap rename to client/capital/__tests__/__snapshots__/index.test.tsx.snap diff --git a/client/capital/test/index.test.tsx b/client/capital/__tests__/index.test.tsx similarity index 98% rename from client/capital/test/index.test.tsx rename to client/capital/__tests__/index.test.tsx index c2a870256dc..e036b6c1e8d 100644 --- a/client/capital/test/index.test.tsx +++ b/client/capital/__tests__/index.test.tsx @@ -7,7 +7,7 @@ import { render, screen } from '@testing-library/react'; * Internal dependencies */ import { useActiveLoanSummary, useLoans } from 'wcpay/data'; -import CapitalPage from '../index'; +import CapitalPage from '..'; // Mock the useLoans hook jest.mock( 'wcpay/data', () => ( { diff --git a/client/card-readers/test/index.test.tsx b/client/card-readers/__tests__/index.test.tsx similarity index 100% rename from client/card-readers/test/index.test.tsx rename to client/card-readers/__tests__/index.test.tsx diff --git a/client/card-readers/index.tsx b/client/card-readers/index.tsx index 9f6d83e74e8..4b2fe9b89cb 100644 --- a/client/card-readers/index.tsx +++ b/client/card-readers/index.tsx @@ -11,7 +11,7 @@ import { __ } from '@wordpress/i18n'; */ import Page from 'components/page'; import ReadersList from './list'; -import { TabPanel } from 'wcpay/components/wp-components-wrapped/components/tab-panel'; +import { TabPanel } from '@wordpress/components'; import './style.scss'; diff --git a/client/card-readers/list/test/index.test.tsx b/client/card-readers/list/__tests__/index.test.tsx similarity index 100% rename from client/card-readers/list/test/index.test.tsx rename to client/card-readers/list/__tests__/index.test.tsx diff --git a/client/card-readers/list/index.tsx b/client/card-readers/list/index.tsx index f8e1824ec6d..7cec0a34dd0 100644 --- a/client/card-readers/list/index.tsx +++ b/client/card-readers/list/index.tsx @@ -8,9 +8,7 @@ import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies */ -import { Card } from 'wcpay/components/wp-components-wrapped/components/card'; -import { CardBody } from 'wcpay/components/wp-components-wrapped/components/card-body'; -import { CardDivider } from 'wcpay/components/wp-components-wrapped/components/card-divider'; +import { Card, CardBody, CardDivider } from '@wordpress/components'; import SettingsSection from 'wcpay/settings/settings-section'; import SettingsLayout from 'wcpay/settings/settings-layout'; import LoadableSettingsSection from 'wcpay/settings/loadable-settings-section'; diff --git a/client/checkout/api/test/index.test.js b/client/checkout/api/__tests__/index.test.js similarity index 100% rename from client/checkout/api/test/index.test.js rename to client/checkout/api/__tests__/index.test.js diff --git a/client/checkout/blocks/test/hooks.test.js b/client/checkout/blocks/__tests__/hooks.test.js similarity index 100% rename from client/checkout/blocks/test/hooks.test.js rename to client/checkout/blocks/__tests__/hooks.test.js diff --git a/client/checkout/blocks/test/payment-method-logos.test.tsx b/client/checkout/blocks/__tests__/payment-method-logos.test.tsx similarity index 100% rename from client/checkout/blocks/test/payment-method-logos.test.tsx rename to client/checkout/blocks/__tests__/payment-method-logos.test.tsx diff --git a/client/checkout/blocks/test/payment-processor.test.js b/client/checkout/blocks/__tests__/payment-processor.test.js similarity index 100% rename from client/checkout/blocks/test/payment-processor.test.js rename to client/checkout/blocks/__tests__/payment-processor.test.js diff --git a/client/checkout/classic/test/3ds-flow-handling.test.js b/client/checkout/classic/__tests__/3ds-flow-handling.test.js similarity index 100% rename from client/checkout/classic/test/3ds-flow-handling.test.js rename to client/checkout/classic/__tests__/3ds-flow-handling.test.js diff --git a/client/checkout/classic/test/payment-processing.test.js b/client/checkout/classic/__tests__/payment-processing.test.js similarity index 100% rename from client/checkout/classic/test/payment-processing.test.js rename to client/checkout/classic/__tests__/payment-processing.test.js diff --git a/client/checkout/stripe-link/test/index.test.js b/client/checkout/stripe-link/__tests__/index.test.js similarity index 100% rename from client/checkout/stripe-link/test/index.test.js rename to client/checkout/stripe-link/__tests__/index.test.js diff --git a/client/checkout/upe-styles/test/index.js b/client/checkout/upe-styles/__tests__/index.test.js similarity index 99% rename from client/checkout/upe-styles/test/index.js rename to client/checkout/upe-styles/__tests__/index.test.js index 3df8e81ba1f..64f502dc14c 100644 --- a/client/checkout/upe-styles/test/index.js +++ b/client/checkout/upe-styles/__tests__/index.test.js @@ -1,7 +1,7 @@ /** * Internal dependencies */ -import * as upeStyles from '../index'; +import * as upeStyles from '..'; describe( 'Getting styles for automated theming', () => { const mockElement = document.createElement( 'input' ); diff --git a/client/checkout/upe-styles/test/utils.js b/client/checkout/upe-styles/__tests__/utils.test.js similarity index 100% rename from client/checkout/upe-styles/test/utils.js rename to client/checkout/upe-styles/__tests__/utils.test.js diff --git a/client/checkout/utils/test/upe.test.js b/client/checkout/utils/__tests__/upe.test.js similarity index 100% rename from client/checkout/utils/test/upe.test.js rename to client/checkout/utils/__tests__/upe.test.js diff --git a/client/checkout/woopay/test/utils.test.js b/client/checkout/woopay/__tests__/utils.test.js similarity index 100% rename from client/checkout/woopay/test/utils.test.js rename to client/checkout/woopay/__tests__/utils.test.js diff --git a/client/checkout/woopay/connect/tests/woopay-connect-iframe.test.js b/client/checkout/woopay/connect/__tests__/woopay-connect-iframe.test.js similarity index 100% rename from client/checkout/woopay/connect/tests/woopay-connect-iframe.test.js rename to client/checkout/woopay/connect/__tests__/woopay-connect-iframe.test.js diff --git a/client/checkout/woopay/connect/woopay-connect.js b/client/checkout/woopay/connect/woopay-connect.js index 3bebed4b8fe..46e74f0ff87 100644 --- a/client/checkout/woopay/connect/woopay-connect.js +++ b/client/checkout/woopay/connect/woopay-connect.js @@ -2,7 +2,7 @@ * Internal dependencies */ import { WooPayConnectIframe } from 'wcpay/checkout/woopay/connect/woopay-connect-iframe'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { getConfig } from 'wcpay/utils/checkout'; import { INJECTED_STATE, @@ -110,7 +110,8 @@ class WoopayConnect { self.listeners.getIframePostMessageCallback = resolve; } ); - ReactDOM.render( , hiddenDiv ); + const root = createRoot( hiddenDiv ); + root.render( ); } /** diff --git a/client/checkout/woopay/direct-checkout/test/index.test.js b/client/checkout/woopay/direct-checkout/__tests__/index.test.js similarity index 100% rename from client/checkout/woopay/direct-checkout/test/index.test.js rename to client/checkout/woopay/direct-checkout/__tests__/index.test.js diff --git a/client/checkout/woopay/direct-checkout/test/woopay-direct-checkout.test.js b/client/checkout/woopay/direct-checkout/__tests__/woopay-direct-checkout.test.js similarity index 100% rename from client/checkout/woopay/direct-checkout/test/woopay-direct-checkout.test.js rename to client/checkout/woopay/direct-checkout/__tests__/woopay-direct-checkout.test.js diff --git a/client/checkout/woopay/express-button/test/express-checkout-iframe.test.js b/client/checkout/woopay/express-button/__tests__/express-checkout-iframe.test.js similarity index 100% rename from client/checkout/woopay/express-button/test/express-checkout-iframe.test.js rename to client/checkout/woopay/express-button/__tests__/express-checkout-iframe.test.js diff --git a/client/checkout/woopay/express-button/test/index.test.js b/client/checkout/woopay/express-button/__tests__/index.test.js similarity index 58% rename from client/checkout/woopay/express-button/test/index.test.js rename to client/checkout/woopay/express-button/__tests__/index.test.js index b11d94bf1a7..d4f09902383 100644 --- a/client/checkout/woopay/express-button/test/index.test.js +++ b/client/checkout/woopay/express-button/__tests__/index.test.js @@ -1,13 +1,12 @@ /** * External dependencies */ -import { screen } from '@testing-library/react'; +import { screen, act } from '@testing-library/react'; /** * Internal dependencies */ -import '../index'; -import { getConfig } from 'utils/checkout'; +import '..'; jest.mock( 'utils/checkout', () => ( { getConfig: jest.fn(), @@ -26,25 +25,33 @@ describe( 'renderWooPayExpressButton', () => { expressButtonContainer.setAttribute( 'id', 'wcpay-woopay-button' ); beforeEach( () => { - getConfig.mockReturnValue( 'foo' ); + document.body.innerHTML = ''; } ); - test( 'render the button component in placeholder', () => { + test( 'render the button component in placeholder', async () => { document.body.appendChild( expressButtonContainer ); // trigger window load. - window.dispatchEvent( new Event( 'load' ) ); + await act( async () => { + window.dispatchEvent( new Event( 'load' ) ); + + // giving React some time to render + await new Promise( ( resolve ) => setTimeout( resolve, 0 ) ); + } ); expect( - screen.queryByText( 'WooPay Express Button' ) + await screen.findByText( 'WooPay Express Button' ) ).toBeInTheDocument(); } ); - test( 'should not render the express button component if placeholder is absent', () => { - document.body.removeChild( expressButtonContainer ); - + test( 'should not render the express button component if placeholder is absent', async () => { // trigger window load. - window.dispatchEvent( new Event( 'load' ) ); + await act( async () => { + window.dispatchEvent( new Event( 'load' ) ); + + // giving React some time to render + await new Promise( ( resolve ) => setTimeout( resolve, 0 ) ); + } ); expect( screen.queryByText( 'WooPay Express Button' ) diff --git a/client/checkout/woopay/express-button/test/woopay-express-checkout-button.test.js b/client/checkout/woopay/express-button/__tests__/woopay-express-checkout-button.test.js similarity index 96% rename from client/checkout/woopay/express-button/test/woopay-express-checkout-button.test.js rename to client/checkout/woopay/express-button/__tests__/woopay-express-checkout-button.test.js index d8993733f56..062c5504db3 100644 --- a/client/checkout/woopay/express-button/test/woopay-express-checkout-button.test.js +++ b/client/checkout/woopay/express-button/__tests__/woopay-express-checkout-button.test.js @@ -189,7 +189,7 @@ describe( 'WoopayExpressCheckoutButton', () => { const expressButton = screen.queryByRole( 'button', { name: 'WooPay', } ); - userEvent.click( expressButton ); + await userEvent.click( expressButton ); await waitFor( () => { expect( request ).toHaveBeenCalledWith( 'woopay.url', { @@ -203,7 +203,7 @@ describe( 'WoopayExpressCheckoutButton', () => { } ); } ); - test( 'call `expressCheckoutIframe` on button click when `isPreview` is false', () => { + test( 'call `expressCheckoutIframe` on button click when `isPreview` is false', async () => { getConfig.mockImplementation( ( v ) => { return v === 'isWoopayFirstPartyAuthEnabled' ? false : 'foo'; } ); @@ -220,7 +220,7 @@ describe( 'WoopayExpressCheckoutButton', () => { const expressButton = screen.queryByRole( 'button', { name: 'WooPay', } ); - userEvent.click( expressButton ); + await userEvent.click( expressButton ); expect( expressCheckoutIframe ).toHaveBeenCalledWith( api, @@ -243,7 +243,7 @@ describe( 'WoopayExpressCheckoutButton', () => { const expressButton = screen.queryByRole( 'button', { name: 'WooPay', } ); - userEvent.click( expressButton ); + await userEvent.click( expressButton ); await waitFor( () => { expect( request ).not.toHaveBeenCalled(); @@ -268,7 +268,7 @@ describe( 'WoopayExpressCheckoutButton', () => { } ); } ); - test( 'should show an alert when clicking the button when add to cart button is disabled', () => { + test( 'should show an alert when clicking the button when add to cart button is disabled', async () => { getConfig.mockImplementation( ( v ) => { return v === 'isWoopayFirstPartyAuthEnabled' ? false : 'foo'; } ); @@ -297,7 +297,7 @@ describe( 'WoopayExpressCheckoutButton', () => { name: 'WooPay', } ); - userEvent.click( expressButton ); + await userEvent.click( expressButton ); expect( window.alert ).toBeCalledWith( 'Please select your product options before proceeding.' @@ -328,7 +328,7 @@ describe( 'WoopayExpressCheckoutButton', () => { name: 'WooPay', } ); - userEvent.click( expressButton ); + await userEvent.click( expressButton ); expect( mockAddToCart ).toHaveBeenCalled(); @@ -363,7 +363,7 @@ describe( 'WoopayExpressCheckoutButton', () => { name: 'WooPay', } ); - userEvent.click( expressButton ); + await userEvent.click( expressButton ); expect( mockAddToCart ).not.toHaveBeenCalled(); diff --git a/client/checkout/woopay/express-button/index.js b/client/checkout/woopay/express-button/index.js index f6645b07518..3b9ccd28833 100644 --- a/client/checkout/woopay/express-button/index.js +++ b/client/checkout/woopay/express-button/index.js @@ -2,7 +2,7 @@ /** * External dependencies */ -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; /** * Internal dependencies @@ -12,7 +12,7 @@ import { WoopayExpressCheckoutButton } from './woopay-express-checkout-button'; import WCPayAPI from '../../api'; import request from '../../utils/request'; -const oldWoopayContainers = []; +const oldWoopayRoots = []; const renderWooPayExpressCheckoutButton = ( listenForCartChanges = {} ) => { // Create an API object, which will be used throughout the checkout. @@ -29,15 +29,16 @@ const renderWooPayExpressCheckoutButton = ( listenForCartChanges = {} ) => { const woopayContainer = document.getElementById( 'wcpay-woopay-button' ); if ( woopayContainer ) { - while ( oldWoopayContainers.length > 0 ) { + while ( oldWoopayRoots.length > 0 ) { // Ensure previous buttons are unmounted and cleaned up. - const oldWoopayContainer = oldWoopayContainers.pop(); - ReactDOM.unmountComponentAtNode( oldWoopayContainer ); + const oldWoopayRoot = oldWoopayRoots.pop(); + oldWoopayRoot.unmount(); } - oldWoopayContainers.push( woopayContainer ); + const root = createRoot( woopayContainer ); + oldWoopayRoots.push( root ); - ReactDOM.render( + root.render( { !! woopayContainer.getAttribute( 'data-product_page' ) } emailSelector="#billing_email" - />, - woopayContainer + /> ); } }; diff --git a/client/checkout/woopay/express-button/woopay-express-checkout-payment-method.js b/client/checkout/woopay/express-button/woopay-express-checkout-payment-method.js index 1ce64ed6d02..aa60ac6eb2d 100644 --- a/client/checkout/woopay/express-button/woopay-express-checkout-payment-method.js +++ b/client/checkout/woopay/express-button/woopay-express-checkout-payment-method.js @@ -2,7 +2,7 @@ * External dependencies */ import { useCallback } from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import { __ } from '@wordpress/i18n'; /** @@ -29,7 +29,7 @@ const WooPayExpressCheckoutButtonContainer = ( { buttonAttributes } ) => { const onRefChange = useCallback( ( node ) => { if ( node ) { - const root = ReactDOM.createRoot( node ); + const root = createRoot( node ); root.render( { } } - ReactDOM.render( - , - checkoutPageSaveUserContainer - ); + const root = createRoot( checkoutPageSaveUserContainer ); + root.render( ); } else { const checkoutPageSaveUserContainer = document.createElement( 'div' ); checkoutPageSaveUserContainer.className = @@ -69,10 +67,8 @@ const renderSaveUserSection = () => { placeOrderButton ); - ReactDOM.render( - , - checkoutPageSaveUserContainer - ); + const root = createRoot( checkoutPageSaveUserContainer ); + root.render( ); } } }; diff --git a/client/components/accordion/test/__snapshots__/accordion.test.tsx.snap b/client/components/accordion/__tests__/__snapshots__/accordion.test.tsx.snap similarity index 100% rename from client/components/accordion/test/__snapshots__/accordion.test.tsx.snap rename to client/components/accordion/__tests__/__snapshots__/accordion.test.tsx.snap diff --git a/client/components/accordion/test/__snapshots__/body.test.tsx.snap b/client/components/accordion/__tests__/__snapshots__/body.test.tsx.snap similarity index 100% rename from client/components/accordion/test/__snapshots__/body.test.tsx.snap rename to client/components/accordion/__tests__/__snapshots__/body.test.tsx.snap diff --git a/client/components/accordion/test/__snapshots__/row.test.tsx.snap b/client/components/accordion/__tests__/__snapshots__/row.test.tsx.snap similarity index 100% rename from client/components/accordion/test/__snapshots__/row.test.tsx.snap rename to client/components/accordion/__tests__/__snapshots__/row.test.tsx.snap diff --git a/client/components/accordion/test/accordion.test.tsx b/client/components/accordion/__tests__/accordion.test.tsx similarity index 100% rename from client/components/accordion/test/accordion.test.tsx rename to client/components/accordion/__tests__/accordion.test.tsx diff --git a/client/components/accordion/test/body.test.tsx b/client/components/accordion/__tests__/body.test.tsx similarity index 100% rename from client/components/accordion/test/body.test.tsx rename to client/components/accordion/__tests__/body.test.tsx diff --git a/client/components/accordion/test/row.test.tsx b/client/components/accordion/__tests__/row.test.tsx similarity index 100% rename from client/components/accordion/test/row.test.tsx rename to client/components/accordion/__tests__/row.test.tsx diff --git a/client/components/accordion/title.tsx b/client/components/accordion/title.tsx index 590e3a8f400..bf172beb765 100644 --- a/client/components/accordion/title.tsx +++ b/client/components/accordion/title.tsx @@ -4,14 +4,13 @@ import React, { forwardRef } from 'react'; import clsx from 'clsx'; import { chevronUp, chevronDown } from '@wordpress/icons'; -import { Icon } from 'wcpay/components/wp-components-wrapped/components/icon'; -import { Button } from 'wcpay/components/wp-components-wrapped/components/button'; +import { Button, Icon } from '@wordpress/components'; +import type { WordPressComponentProps } from '@wordpress/components/ui/context/wordpress-component'; /** * Internal dependencies */ import type { AccordionTitleProps } from './types'; -import type { WordPressComponentProps } from '@wordpress/components/ui/context/wordpress-component'; import AccordionSubtitle from './subtitle'; import './style.scss'; @@ -34,7 +33,6 @@ const AccordionTitle = forwardRef< 'is-md': md, 'is-lg': lg, } ) } - // @ts-expect-error: there is a type discrepancy between the wrapped WP components and the bundled components. ref={ ref } { ...props } > @@ -44,7 +42,6 @@ const AccordionTitle = forwardRef< */ }