diff --git a/.github/actions/e2e-pw/run-log-tests/action.yml b/.github/actions/e2e-pw/run-log-tests/action.yml new file mode 100644 index 00000000000..d8f85f00285 --- /dev/null +++ b/.github/actions/e2e-pw/run-log-tests/action.yml @@ -0,0 +1,17 @@ +name: 'Run Tests' +description: 'Runs Playwright E2E tests' + +runs: + using: 'composite' + steps: + - name: First Run Playwright E2E Tests + id: first_run_e2e_pw_tests + # Use +e to trap errors when running E2E tests. + shell: /bin/bash +e {0} + run: npm run test:e2e-pw-ci + - uses: actions/upload-artifact@v3 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 7 diff --git a/.github/workflows/e2e-pw-pull-request.yml b/.github/workflows/e2e-pw-pull-request.yml new file mode 100644 index 00000000000..0cc22f767c2 --- /dev/null +++ b/.github/workflows/e2e-pw-pull-request.yml @@ -0,0 +1,74 @@ +name: E2E Playwright Tests - Pull Request + +on: + pull_request: + branches: + - develop + - trunk + workflow_dispatch: + workflow_call: + inputs: + wcpay-use-build-artifact: + type: boolean + required: false + default: false + repo-branch: + type: string + required: false + description: 'Branch to be used for running tests' + +env: + E2E_GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }} + WCP_DEV_TOOLS_REPO: ${{ secrets.WCP_DEV_TOOLS_REPO }} + WCP_DEV_TOOLS_BRANCH: 'trunk' + WCP_SERVER_REPO: ${{ secrets.WCP_SERVER_REPO }} + WC_SUBSCRIPTIONS_REPO: ${{ secrets.WC_SUBSCRIPTIONS_REPO }} + E2E_BLOG_ID: ${{ secrets.E2E_BLOG_ID }} + E2E_BLOG_TOKEN: ${{ secrets.E2E_BLOG_TOKEN }} + E2E_USER_TOKEN: ${{ secrets.E2E_USER_TOKEN }} + WC_E2E_SCREENSHOTS: 1 + E2E_SLACK_CHANNEL: ${{ secrets.E2E_SLACK_CHANNEL }} + E2E_SLACK_TOKEN: ${{ secrets.E2E_SLACK_TOKEN }} + E2E_USE_LOCAL_SERVER: false + E2E_RESULT_FILEPATH: 'tests/e2e/results.json' + WCPAY_USE_BUILD_ARTIFACT: ${{ inputs.wcpay-use-build-artifact }} + WCPAY_ARTIFACT_DIRECTORY: 'zipfile' + NODE_ENV: 'test' + FORCE_E2E_DEPS_SETUP: true + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + wcpay-e2e-tests: + runs-on: ubuntu-latest + + name: WC - latest + + env: + E2E_WP_VERSION: 'latest' + E2E_WC_VERSION: 'latest' + + steps: + - name: Checkout WCPay repository + uses: actions/checkout@v4 + with: + ref: ${{ inputs.repo-branch || github.ref }} + + - name: 'Download WooCommerce Payments build file' + if: ${{ inputs.wcpay-use-build-artifact }} + uses: actions/download-artifact@v4 + with: + name: woocommerce-payments + path: ${{ env.WCPAY_ARTIFACT_DIRECTORY }} + + - name: Setup E2E environment + uses: ./.github/actions/e2e/env-setup + + - name: Install Playwright + shell: bash + run: npx playwright install chromium + + - name: Run tests, upload screenshots & logs + uses: ./.github/actions/e2e-pw/run-log-tests diff --git a/.github/workflows/post-release-updates.yml b/.github/workflows/post-release-updates.yml index 813c9fd0bc1..bb9a1ef1175 100644 --- a/.github/workflows/post-release-updates.yml +++ b/.github/workflows/post-release-updates.yml @@ -155,8 +155,10 @@ jobs: echo ":warning: File "$NEXT_RELEASE_VERSION_INSTRUCTIONS_FILENAME.md" already exists. No action needed." >> $GITHUB_STEP_SUMMARY fi - # If an entry for the next version doesn't exist yet + # Check if this release version exists in Release-testing-instructions.md if ! grep -q "v$NEXT_RELEASE_VERSION" Release-testing-instructions.md; then + # If it doesn't exist, remove all trailing newlines and add the new version for this release + perl -pi -e 'BEGIN{undef $/;} s/\n+\z//' Release-testing-instructions.md echo -ne "\n* [v$NEXT_RELEASE_VERSION](https://github.com/Automattic/woocommerce-payments/wiki/$NEXT_RELEASE_VERSION_INSTRUCTIONS_FILENAME)" >> Release-testing-instructions.md echo "Added a new entry for v$NEXT_RELEASE_VERSION in \"Release-testing-instructions.md\"." >> $GITHUB_STEP_SUMMARY HAS_CHANGES=true diff --git a/.gitignore b/.gitignore index 4aabb410301..a0125db32a6 100644 --- a/.gitignore +++ b/.gitignore @@ -87,5 +87,12 @@ tests/e2e/screenshots # E2E Performance test results tests/e2e/reports +# E2E Playwright +/playwright-report/ +/blob-report/ +tests/e2e-pw/.auth/ +tests/e2e-pw/test-results/ +tests/e2e-pw/playwright/.cache/ +tests/e2e-pw/tests/e2e-pw/.auth/* # Slate docs docs/rest-api/build/* diff --git a/README.md b/README.md index 4e3804e580c..80174d5115a 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ Install the following plugins: - WooCommerce - WCPay Dev Tools (clone or download [the GitHub repo](https://github.com/Automattic/woocommerce-payments-dev-tools)) + - This dependency is automatically updated to the latest version each time you perform a `git pull` or `git merge` in this repository, as long as the WCPay Dev Tools repository is cloned locally and remains on the `trunk` branch. For more details, please refer to the [post-merge](.husky/post-merge) hook. ### Optional local.env file diff --git a/assets/css/success.css b/assets/css/success.css index 6d5200174b0..8ada2af0ee6 100644 --- a/assets/css/success.css +++ b/assets/css/success.css @@ -1,11 +1,15 @@ -.wc-payment-gateway-method-name-woopay-wrapper { +.wc-payment-gateway-method-logo-wrapper { display: flex; align-items: center; flex-wrap: wrap; line-height: 1; } -.wc-payment-gateway-method-name-woopay-wrapper img { +.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; +} diff --git a/assets/css/success.rtl.css b/assets/css/success.rtl.css index a319b0a35cf..16c136a0b1e 100644 --- a/assets/css/success.rtl.css +++ b/assets/css/success.rtl.css @@ -1,11 +1,15 @@ -.wc-payment-gateway-method-name-woopay-wrapper { +.wc-payment-gateway-method-logo-wrapper { display: flex; align-items: center; flex-wrap: wrap; line-height: 1; } -.wc-payment-gateway-method-name-woopay-wrapper img { +.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; +} diff --git a/changelog.txt b/changelog.txt index 58379bedca4..9acb462bac0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,41 @@ *** WooPayments Changelog *** += 7.6.0 - 2024-05-08 = +* Add - Add additional data to Compatibility service +* Add - Add User Satisfaction Survey for Payments Overview Widget +* Add - Detect payment methods enabled by multiple payment gateways. +* Add - Display BNPL payment method logos on the thank you page. +* Add - Non user-facing changes. Behind feature flag. Add tooltip messages to tiles within Payment activity widget +* Add - Not user-facing: hidden behind feature flag. Use Reporting API to fetch and populate data in the Payment Activity widget. +* Add - Pre check save my info for eligible contries +* Add - Support for starting auto-renewing subscriptions for In-Person Payments. +* Fix - Add notice when no rules are enabled in advanced fraud settings +* Fix - Adjust positioning of BNPL messaging on the classic cart page. +* Fix - Avoid updating billing details for legacy card objects. +* Fix - Ensure the WooPay preview in the admin dashboard matches the actual implementation. +* Fix - fix: BNPL announcement link. +* Fix - fix: Stripe terms warning at checkout when Link is enabled +* Fix - Fix issue with transient check related to fraud protection settings. +* Fix - Fix order notes entry and risk meta box content when a payment is blocked due to AVS checks while the corresponding advanced fraud rule is enabled. +* Fix - Fix type error for fraud outcome API. +* Fix - Fix WooPay tracks user ID for logged in users. +* Fix - Hide Fraud info banner until first transaction happens +* Fix - Improve merchant session request with preloaded data. +* Fix - Improve signing of minimum WooPay session data. +* Fix - Make sure an explicit currency code is present in the cart and checkout blocks when multi-currency is enabled +* Fix - Prevent Stripe Link from triggering the checkout fields warning +* Fix - Remove risk review request from the transactions page. +* Fix - Resolves "Invalid recurring shipping method" errors when purchasing multiple subscriptions with Apple Pay and Google Pay. +* Fix - Revert: Add Multi-Currency Support to Page Caching via Cookies. +* Update - Add source param to onboarding and complete KYC links +* Update - Add support of a third-party plugin with PRBs into duplicates detection mechanism. +* Update - Remove feature flag for the pay-for-order flow +* Dev - Add Playwright e2e test suite ready for incremental migration and visual regression testing +* Dev - Avoid warnings about fatal error during plugin update due to problems with plugin initialization. +* Dev - Remove legacy method from `WooPay_Utilities`. +* Dev - Remove obsolete docker-compose key `version` +* Dev - Upgraded jetpack sync package version. + = 7.5.3 - 2024-04-22 = * Fix - Fix subscription renewals exceptions * Dev - Remove deprecated param from asset data registry interface. diff --git a/client/checkout/blocks/index.js b/client/checkout/blocks/index.js index 5dd0bc9f0db..6baad3bdbea 100644 --- a/client/checkout/blocks/index.js +++ b/client/checkout/blocks/index.js @@ -11,7 +11,7 @@ import { /** * Internal dependencies */ -import { getUPEConfig } from 'utils/checkout'; +import { getUPEConfig, getConfig } from 'utils/checkout'; import { isLinkEnabled } from '../utils/upe'; import WCPayAPI from '../api'; import { SavedTokenHandler } from './saved-token-handler'; @@ -158,3 +158,22 @@ window.addEventListener( 'load', () => { enqueueFraudScripts( getUPEConfig( 'fraudServices' ) ); addCheckoutTracking(); } ); + +// If multi-currency is enabled, add currency code to total amount in cart and checkout blocks. +if ( getConfig( 'isMultiCurrencyEnabled' ) ) { + const { registerCheckoutFilters } = window.wc.blocksCheckout; + + const modifyTotalsPrice = ( defaultValue, extensions, args ) => { + const { cart } = args; + + if ( cart?.cartTotals?.currency_code ) { + return ` ${ cart.cartTotals.currency_code }`; + } + + return defaultValue; + }; + + registerCheckoutFilters( 'woocommerce-payments', { + totalValue: modifyTotalsPrice, + } ); +} diff --git a/client/checkout/blocks/style.scss b/client/checkout/blocks/style.scss index daf09c07a85..06477415a0f 100644 --- a/client/checkout/blocks/style.scss +++ b/client/checkout/blocks/style.scss @@ -44,37 +44,48 @@ button.wcpay-stripelink-modal-trigger:hover { border-color: transparent; } -.wc-block-checkout__payment-method - .wc-block-components-radio-control__label - span { - width: 95%; - - &:has( .StripeElement ) { - display: grid; - grid-template-columns: 1fr auto; - } +.wc-block-checkout__payment-method { + .wc-block-components-radio-control__label span { + width: 95%; - img { - float: right; - border: 0; - padding: 0; - height: 24px; - max-height: 24px; - } + &:has( .StripeElement ) { + display: grid; + grid-template-columns: 1fr auto; + } - .StripeElement { - width: 100%; - grid-column: 1 / span 2; - grid-row-start: 2; - pointer-events: none; + img { + float: right; + border: 0; + padding: 0; + height: 24px; + max-height: 24px; + } - + img { - grid-row: 1 / span 2; - grid-column: 2; + .StripeElement { + width: 100%; + grid-column: 1 / span 2; + grid-row-start: 2; + pointer-events: none; + + + img { + grid-row: 1 / span 2; + grid-column: 2; + } } } } +#remember-me { + margin-top: 36px; + + h2 { + font-size: 18px; + font-weight: 600; + line-height: 21.6px; + letter-spacing: -0.01em; + } +} + #payment-method { label.wc-block-components-radio-control__option-checked { .StripeElement { diff --git a/client/checkout/utils/upe.js b/client/checkout/utils/upe.js index 27876f1af5d..65cdb5718aa 100644 --- a/client/checkout/utils/upe.js +++ b/client/checkout/utils/upe.js @@ -13,7 +13,9 @@ import { getPaymentMethodsConstants } from '../constants'; */ export const getTerms = ( paymentMethodsConfig, value = 'always' ) => { const reusablePaymentMethods = Object.keys( paymentMethodsConfig ).filter( - ( method ) => paymentMethodsConfig[ method ].isReusable + ( method ) => + // Stripe link doesn't need the "terms" - adding this property causes a warning in the console. + method !== 'link' && paymentMethodsConfig[ method ].isReusable ); return reusablePaymentMethods.reduce( ( obj, method ) => { diff --git a/client/checkout/woopay/direct-checkout/woopay-direct-checkout.js b/client/checkout/woopay/direct-checkout/woopay-direct-checkout.js index 6bd5ee33d34..7847bd7de74 100644 --- a/client/checkout/woopay/direct-checkout/woopay-direct-checkout.js +++ b/client/checkout/woopay/direct-checkout/woopay-direct-checkout.js @@ -6,7 +6,6 @@ import request from 'wcpay/checkout/utils/request'; import { buildAjaxURL } from 'wcpay/payment-request/utils'; import UserConnect from 'wcpay/checkout/woopay/connect/user-connect'; import SessionConnect from 'wcpay/checkout/woopay/connect/session-connect'; -import { getTracksIdentity } from 'tracks'; /** * The WooPayDirectCheckout class is responsible for injecting the WooPayConnectIframe into the @@ -173,22 +172,18 @@ class WooPayDirectCheckout { throw new Error( 'Invalid encrypted session data.' ); } - const testMode = getConfig( 'testMode' ); + const { + blog_id, // eslint-disable-line camelcase + data: { session, iv, hash }, + } = redirectData; const redirectParams = new URLSearchParams( { checkout_redirect: 1, - blog_id: redirectData.blog_id, - session: redirectData.data.session, - iv: redirectData.data.iv, - hash: redirectData.data.hash, - testMode, - source_url: window.location.href, + blog_id, + session, + iv, + hash, } ); - const tracksUserId = await getTracksIdentity(); - if ( tracksUserId ) { - redirectParams.append( 'tracksUserIdentity', tracksUserId ); - } - const redirectUrl = getConfig( 'woopayHost' ) + '/woopay/?' + redirectParams.toString(); diff --git a/client/checkout/woopay/email-input-iframe.js b/client/checkout/woopay/email-input-iframe.js index 74ddd397bf3..2538de85008 100644 --- a/client/checkout/woopay/email-input-iframe.js +++ b/client/checkout/woopay/email-input-iframe.js @@ -421,6 +421,12 @@ export const handleWooPayEmailInput = async ( openIframe( email ); } else if ( data.code !== 'rest_invalid_param' ) { recordUserEvent( 'checkout_woopay_save_my_info_offered' ); + + if ( window.woopayCheckout?.PRE_CHECK_SAVE_MY_INFO ) { + recordUserEvent( 'checkout_save_my_info_click', { + status: 'checked', + } ); + } } } ) .catch( ( err ) => { diff --git a/client/checkout/woopay/index.js b/client/checkout/woopay/index.js index 1bb5eed4a58..425683e9117 100644 --- a/client/checkout/woopay/index.js +++ b/client/checkout/woopay/index.js @@ -23,21 +23,13 @@ const renderSaveUserSection = () => { ); if ( blocksCheckout.length ) { - const checkoutPageSaveUserContainer = document.createElement( - 'fieldset' - ); + const checkoutPageSaveUserContainer = document.createElement( 'div' ); const paymentOptions = document.getElementsByClassName( 'wp-block-woocommerce-checkout-payment-block' )?.[ 0 ]; - const isPaymentOptionsNumbered = paymentOptions?.classList?.contains( - 'wc-block-components-checkout-step--with-step-number' - ); checkoutPageSaveUserContainer.className = - 'wc-block-checkout__payment-method wp-block-woocommerce-checkout-remember-block ' + - `wc-block-components-checkout-step wc-block-components-checkout-step${ - isPaymentOptionsNumbered ? '--with-step-number' : '' - }`; + 'wc-block-checkout__payment-method wp-block-woocommerce-checkout-remember-block '; checkoutPageSaveUserContainer.id = 'remember-me'; if ( paymentOptions ) { diff --git a/client/components/account-status/account-tools/index.tsx b/client/components/account-status/account-tools/index.tsx index 9e2b255a6b5..e417d4349ed 100644 --- a/client/components/account-status/account-tools/index.tsx +++ b/client/components/account-status/account-tools/index.tsx @@ -29,7 +29,9 @@ const handleReset = () => { }; export const AccountTools: React.FC< Props > = ( props: Props ) => { - const accountLink = props.accountLink; + const accountLink = addQueryArgs( props.accountLink, { + source: 'account-tools__finish-setup-button', + } ); const detailsSubmitted = props.detailsSubmitted; const [ modalVisible, setModalVisible ] = useState( false ); diff --git a/client/components/account-status/account-tools/test/__snapshots__/index.test.tsx.snap b/client/components/account-status/account-tools/test/__snapshots__/index.test.tsx.snap index b5e4c2ed3b2..b5b1f5eb8fc 100644 --- a/client/components/account-status/account-tools/test/__snapshots__/index.test.tsx.snap +++ b/client/components/account-status/account-tools/test/__snapshots__/index.test.tsx.snap @@ -23,7 +23,7 @@ exports[`AccountTools should render in live mode 1`] = ` > Finish setup @@ -62,7 +62,7 @@ exports[`AccountTools should render in sandbox mode 1`] = ` > Finish setup diff --git a/client/components/account-status/index.js b/client/components/account-status/index.js index 581d494b415..62451e9f121 100755 --- a/client/components/account-status/index.js +++ b/client/components/account-status/index.js @@ -26,6 +26,7 @@ import './shared.scss'; import { AccountTools } from './account-tools'; import { isInDevMode } from 'wcpay/utils'; import { recordEvent } from 'wcpay/tracks'; +import { addQueryArgs } from '@wordpress/url'; const AccountStatusCard = ( props ) => { const { title, children, value } = props; @@ -60,7 +61,9 @@ const AccountStatusError = () => { const AccountStatusDetails = ( props ) => { const { accountStatus, accountFees } = props; - + const accountLink = addQueryArgs( accountStatus.accountLink, { + source: 'account-details', + } ); const cardTitle = ( <> @@ -83,7 +86,7 @@ const AccountStatusDetails = ( props ) => { source: 'account-details', } ) } - href={ accountStatus.accountLink } + href={ accountLink } target={ '_blank' } > { __( 'Edit details', 'woocommerce-payments' ) } diff --git a/client/components/account-status/test/__snapshots__/index.js.snap b/client/components/account-status/test/__snapshots__/index.js.snap index 86b224a66e8..97a0ae5fc41 100644 --- a/client/components/account-status/test/__snapshots__/index.js.snap +++ b/client/components/account-status/test/__snapshots__/index.js.snap @@ -79,12 +79,13 @@ exports[`AccountStatus renders normal status 1`] = ` data-wp-c16t="true" data-wp-component="FlexItem" > - +
- + + ); +}; + +export default Emoticon; diff --git a/client/components/payment-activity/survey/index.tsx b/client/components/payment-activity/survey/index.tsx new file mode 100644 index 00000000000..cb2bd8abe16 --- /dev/null +++ b/client/components/payment-activity/survey/index.tsx @@ -0,0 +1,199 @@ +/** @format **/ + +/** + * External dependencies + */ +import React from 'react'; +import { HorizontalRule } from '@wordpress/primitives'; +import { Button, CardFooter, TextareaControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { createInterpolateElement, useState } from '@wordpress/element'; +import { Icon, closeSmall } from '@wordpress/icons'; + +/** + * Internal dependencies. + */ +import type { Rating } from './types'; +import { useOverviewSurveyContext } from './context'; +import Emoticon from './emoticon'; +import './style.scss'; + +const Survey: React.FC = () => { + const { + responseStatus, + surveySubmitted, + surveyAnswers, + setSurveyAnswers, + setSurveySubmitted, + } = useOverviewSurveyContext(); + + const [ showComponent, setShowComponent ] = useState( true ); + + const currentRating = surveyAnswers.rating; + const ratingWithComment: Rating[] = [ + 'very-unhappy', + 'unhappy', + 'neutral', + ]; + const ratings: Rating[] = [ + 'very-unhappy', + 'unhappy', + 'neutral', + 'happy', + 'very-happy', + ]; + const showComment = + currentRating && ratingWithComment.includes( currentRating ); + const disableForm = 'pending' === responseStatus; + + const setReviewRating = function ( value?: Rating ) { + const answers = { + ...surveyAnswers, + rating: value, + }; + setSurveyAnswers( answers ); + + // If the user selects a rating that does not require a comment, submit the survey immediately. + if ( value && ! ratingWithComment.includes( value ) ) { + setSurveySubmitted( answers ); + } + }; + + if ( ! showComponent ) { + return null; + } + + if ( surveySubmitted ) { + return ( + +
+
+ + πŸ™Œ + + { __( + 'We appreciate your feedback!', + 'woocommerce-payments' + ) } +
+ +
+ +
+
+
+ ); + } + + return ( + +
+
+ { __( + 'Are these metrics helpful?', + 'woocommerce-payments' + ) } + +
+ { ratings.map( ( rating ) => ( + setReviewRating( rating ) } + isSelected={ rating === currentRating } + /> + ) ) } +
+
+ + { showComment && ( + <> +
+ +
+ + + +
+ { + setSurveyAnswers( ( prev ) => ( { + ...prev, + comments: text, + } ) ); + } } + value={ surveyAnswers.comments ?? '' } + readOnly={ disableForm } + /> +

+ { createInterpolateElement( + __( + 'Your feedback will be only be shared with WooCommerce and treated pursuant to our privacy policy.', + 'woocommerce-payments' + ), + { + a: ( + // eslint-disable-next-line jsx-a11y/anchor-has-content + + ), + } + ) } +

+
+ +
+ + +
+ + ) } +
+
+ ); +}; +export default Survey; diff --git a/client/components/payment-activity/survey/style.scss b/client/components/payment-activity/survey/style.scss new file mode 100644 index 00000000000..33972d75bf8 --- /dev/null +++ b/client/components/payment-activity/survey/style.scss @@ -0,0 +1,56 @@ +.wcpay-payments-activity__survey { + position: relative; + width: 100%; + + .components-button.has-icon { + min-width: 32px; + height: 32px; + } + + .survey_container { + margin: 0 auto; + display: flex; + gap: 10px; + justify-content: center; + align-items: center; + + span[role='img'] { + line-height: 32px; + font-size: 20px; + } + + &__emoticons { + display: flex; + justify-content: flex-end; + + .selected { + background-color: $wp-blue-0; + } + } + + @include breakpoint( '<660px' ) { + flex-direction: column; + } + } + + .close_container { + position: absolute; + top: 0; + right: 0; + } + + hr { + margin: 16px auto; + } + + .comment_container { + max-width: 500px; + margin: 0 auto; + + &__disclaimer { + font-size: 11px; + color: $wp-gray-40; + font-style: italic; + } + } +} diff --git a/client/components/payment-activity/survey/test/__snapshots__/index.test.tsx.snap b/client/components/payment-activity/survey/test/__snapshots__/index.test.tsx.snap new file mode 100644 index 00000000000..571ede8a94e --- /dev/null +++ b/client/components/payment-activity/survey/test/__snapshots__/index.test.tsx.snap @@ -0,0 +1,234 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`WcPayOverviewSurveyContextProvider test survey initial display 1`] = ` +
+ +
+`; + +exports[`WcPayOverviewSurveyContextProvider test survey with comments textbox 1`] = ` +
+