Commit 0bc7bb2a4c3 for woocommerce
commit 0bc7bb2a4c37da44ad507d5fff6a90707feacb61
Author: Rubens Castro <orubenscastro@gmail.com>
Date: Mon Oct 5 10:19:02 2026 -0300
Add Checkout block incompatibility badge to Payments settings (#67601)
* Add Checkout block incompatibility badge to Payments settings
* Add changelog entry for Checkout block incompatibility badge
* Remove trailing slash from documentation link anchor
* Make Checkout block compatibility tests self-contained
* Changes copy, removes underscore from badge icon
* Update incompatibility tooltip copy to reference classic checkout
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Fix typo in incompatibility tooltip copy (Payments -> Payment)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Re-trigger CI (flaky PHP 7.4 composer bin install race)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Update plugins/woocommerce/src/Internal/Admin/Settings/PaymentsController.php
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Update plugins/woocommerce/src/Internal/Admin/Settings/PaymentsController.php
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Update plugins/woocommerce/src/Internal/Admin/Settings/PaymentsController.php
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Update plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsControllerTest.php
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Update plugins/woocommerce/client/admin/client/settings-payments/settings-payments-main.scss
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Update plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list-item/test/payment-gateway-list-item.test.tsx
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Update plugins/woocommerce/changelog/62707-add-payment-gateway-checkout-compatibility-warning
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Update plugins/woocommerce/client/admin/client/typings/global.d.ts
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Update plugins/woocommerce/src/Internal/Admin/Settings/PaymentsController.php
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Update plugins/woocommerce/src/Internal/Admin/Settings/PaymentsController.php
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
* Remove unnecessary delete_option line
* Address payment gateway compatibility review feedback
* Fix payment gateway compatibility test formatting
* Fix prettier formatting in payment gateway list item
* Remove external link style override from status badge popover
* Use the design system Link in the compatibility badge popover
* Match the compatibility popover link to the page's Link pattern
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/62707-add-payment-gateway-checkout-compatibility-warning b/plugins/woocommerce/changelog/62707-add-payment-gateway-checkout-compatibility-warning
new file mode 100644
index 00000000000..07a5c5b0657
--- /dev/null
+++ b/plugins/woocommerce/changelog/62707-add-payment-gateway-checkout-compatibility-warning
@@ -0,0 +1,4 @@
+Significance: minor
+Type: add
+
+Show a "Limited compatibility" badge on the Payments settings page when an enabled payment gateway has no Checkout block integration.
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list-item/payment-gateway-list-item.tsx b/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list-item/payment-gateway-list-item.tsx
index 81189466e88..2316eee8fb1 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list-item/payment-gateway-list-item.tsx
+++ b/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list-item/payment-gateway-list-item.tsx
@@ -6,6 +6,8 @@ import { __ } from '@wordpress/i18n';
import { decodeEntities } from '@wordpress/html-entities';
import { PaymentGatewayProvider } from '@woocommerce/data';
import { Tooltip } from '@wordpress/components';
+import { createInterpolateElement } from '@wordpress/element';
+import { Link } from '@woocommerce/components';
/**
* Internal dependencies
@@ -49,6 +51,13 @@ export const PaymentGatewayListItem = ( {
const itemIsWooPayments = isWooPayments( gateway.id );
const incentive = hasIncentive( gateway ) ? gateway._incentive : null;
+ const isIncompatibleWithCheckoutBlock =
+ gateway.state.enabled &&
+ (
+ window.wcSettings?.admin?.woocommerce_checkout_block_compatibility
+ ?.incompatible_gateway_ids ?? []
+ ).includes( gateway.id );
+
const gatewayHasRecommendedPaymentMethods =
( gateway.onboarding?.recommended_payment_methods ?? [] ).length > 0;
@@ -153,6 +162,37 @@ export const PaymentGatewayListItem = ( {
popoverContent={ determineGatewayStatusMessage() }
/>
) }
+ { isIncompatibleWithCheckoutBlock && (
+ <StatusBadge
+ status="not_supported"
+ message={ __(
+ 'Limited compatibility',
+ 'woocommerce'
+ ) }
+ popoverContent={
+ <p>
+ { createInterpolateElement(
+ __(
+ 'Payment methods from this provider will only appear on classic checkout. <a>Learn more</a>',
+ 'woocommerce'
+ ),
+ {
+ a: (
+ <Link
+ href="https://woocommerce.com/document/woocommerce-store-editing/customizing-cart-and-checkout/#incompatible-extensions"
+ target="_blank"
+ rel="noreferrer"
+ type="external"
+ >
+ { null }
+ </Link>
+ ),
+ }
+ ) }
+ </p>
+ }
+ />
+ ) }
{ /* If the gateway has a matching suggestion, it is an official extension. */ }
{ gateway._suggestion_id && (
<OfficialBadge
diff --git a/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list-item/test/payment-gateway-list-item.test.tsx b/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list-item/test/payment-gateway-list-item.test.tsx
index cc5d0210da0..26ccaa16021 100644
--- a/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list-item/test/payment-gateway-list-item.test.tsx
+++ b/plugins/woocommerce/client/admin/client/settings-payments/components/payment-gateway-list-item/test/payment-gateway-list-item.test.tsx
@@ -31,13 +31,15 @@ jest.mock( '~/lib/sanitize-html', () => ( {
jest.mock( '~/settings-payments/components/status-badge', () => ( {
StatusBadge: ( {
status,
+ message,
popoverContent,
}: {
status: string;
+ message?: string;
popoverContent?: React.ReactNode;
} ) => (
<div data-testid="status-badge" data-status={ status }>
- StatusBadge-{ status }
+ { message || `StatusBadge-${ status }` }
{ popoverContent && (
<div data-testid="status-badge-popover">{ popoverContent }</div>
) }
@@ -46,37 +48,34 @@ jest.mock( '~/settings-payments/components/status-badge', () => ( {
} ) );
jest.mock( '~/settings-payments/components/ellipsis-menu-content', () => ( {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Mock is used by PaymentGatewayListItem component
EllipsisMenuWrapper: ( { provider }: { provider: { id: string } } ) => (
<div data-testid="ellipsis-menu">EllipsisMenu-{ provider.id }</div>
),
} ) );
jest.mock( '~/settings-payments/components/sortable', () => ( {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Mock is used by PaymentGatewayListItem component
DefaultDragHandle: () => <div data-testid="drag-handle">DragHandle</div>,
} ) );
jest.mock( '~/settings-payments/components/buttons', () => ( {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Mock is used by PaymentGatewayListItem component
ActivatePaymentsButton: ( { incentive }: { incentive?: unknown } ) => (
<button data-testid="activate-payments-button">
ActivatePayments{ incentive ? '-with-incentive' : '' }
</button>
),
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Mock is used by PaymentGatewayListItem component
+
CompleteSetupButton: ( { disabled }: { disabled?: boolean } ) => (
<button data-testid="complete-setup-button" disabled={ disabled }>
CompleteSetup
</button>
),
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Mock is used by PaymentGatewayListItem component
+
EnableGatewayButton: ( { incentive }: { incentive?: unknown } ) => (
<button data-testid="enable-gateway-button">
Enable{ incentive ? '-with-incentive' : '' }
</button>
),
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Mock is used by PaymentGatewayListItem component
+
SettingsButton: () => (
<button data-testid="settings-button">Settings</button>
),
@@ -85,7 +84,6 @@ jest.mock( '~/settings-payments/components/buttons', () => ( {
jest.mock(
'~/settings-payments/components/buttons/reactivate-live-payments-button',
() => ( {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Mock is used by PaymentGatewayListItem component
ReactivateLivePaymentsButton: () => (
<button data-testid="reactivate-live-payments-button">
ReactivateLivePayments
@@ -95,20 +93,19 @@ jest.mock(
);
jest.mock( '~/settings-payments/components/incentive-status-badge', () => ( {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Mock is used by PaymentGatewayListItem component
IncentiveStatusBadge: ( { incentive }: { incentive: { id: string } } ) => (
<div data-testid="incentive-badge">Incentive-{ incentive.id }</div>
),
} ) );
jest.mock( '~/settings-payments/components/official-badge', () => ( {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- Mock is used by PaymentGatewayListItem component
OfficialBadge: ( { suggestionId }: { suggestionId: string } ) => (
<div data-testid="official-badge">Official-{ suggestionId }</div>
),
} ) );
jest.mock( '@wordpress/components', () => ( {
+ ...jest.requireActual( '@wordpress/components' ),
Tooltip: ( { children }: { children: React.ReactNode } ) => (
<div>{ children }</div>
),
@@ -623,6 +620,151 @@ describe( 'PaymentGatewayListItem', () => {
} );
} );
+ describe( 'Checkout Block Incompatibility Badge', () => {
+ const enabledGatewayState = {
+ enabled: true,
+ account_connected: true,
+ needs_setup: false,
+ test_mode: false,
+ dev_mode: false,
+ };
+
+ const onboardedGateway = {
+ state: {
+ supported: true,
+ started: true,
+ completed: true,
+ test_mode: false,
+ },
+ messages: {},
+ _links: {
+ onboard: { href: '/onboard' },
+ reset: { href: '/reset' },
+ },
+ recommended_payment_methods: [],
+ type: 'standard',
+ };
+
+ const setIncompatibleGatewayIds = ( ids: string[] ) => {
+ window.wcSettings.admin.woocommerce_checkout_block_compatibility = {
+ incompatible_gateway_ids: ids,
+ };
+ };
+
+ afterEach( () => {
+ delete window.wcSettings.admin
+ .woocommerce_checkout_block_compatibility;
+ } );
+
+ it( 'shows the badge when an enabled gateway is incompatible', () => {
+ setIncompatibleGatewayIds( [ 'test-gateway' ] );
+ const gateway = createMockGateway( {
+ state: enabledGatewayState,
+ onboarding: onboardedGateway,
+ } );
+ const { getByText, getAllByTestId } = render(
+ <PaymentGatewayListItem
+ gateway={ gateway }
+ { ...defaultProps }
+ />
+ );
+
+ expect( getByText( 'Limited compatibility' ) ).toBeInTheDocument();
+ expect(
+ getAllByTestId( 'status-badge' ).map( ( badge ) =>
+ badge.getAttribute( 'data-status' )
+ )
+ ).toEqual( [ 'active', 'not_supported' ] );
+ } );
+
+ it( 'explains the incompatibility in the badge popover', () => {
+ setIncompatibleGatewayIds( [ 'test-gateway' ] );
+ const gateway = createMockGateway( {
+ state: enabledGatewayState,
+ } );
+ const { getByTestId } = render(
+ <PaymentGatewayListItem
+ gateway={ gateway }
+ { ...defaultProps }
+ />
+ );
+
+ expect( getByTestId( 'status-badge-popover' ) ).toHaveTextContent(
+ 'Payment methods from this provider will only appear on classic checkout.'
+ );
+ } );
+
+ it( 'links to the incompatible extensions documentation from the popover', () => {
+ setIncompatibleGatewayIds( [ 'test-gateway' ] );
+ const gateway = createMockGateway( {
+ state: enabledGatewayState,
+ } );
+ const { getByRole } = render(
+ <PaymentGatewayListItem
+ gateway={ gateway }
+ { ...defaultProps }
+ />
+ );
+
+ expect(
+ getByRole( 'link', { name: /Learn more/ } )
+ ).toHaveAttribute(
+ 'href',
+ 'https://woocommerce.com/document/woocommerce-store-editing/customizing-cart-and-checkout/#incompatible-extensions'
+ );
+ } );
+
+ it( 'does not show the badge when the gateway is not incompatible', () => {
+ setIncompatibleGatewayIds( [ 'another-gateway' ] );
+ const gateway = createMockGateway( {
+ state: enabledGatewayState,
+ } );
+ const { queryByText } = render(
+ <PaymentGatewayListItem
+ gateway={ gateway }
+ { ...defaultProps }
+ />
+ );
+
+ expect(
+ queryByText( 'Limited compatibility' )
+ ).not.toBeInTheDocument();
+ } );
+
+ it( 'does not show the badge when the incompatible gateway is disabled', () => {
+ setIncompatibleGatewayIds( [ 'test-gateway' ] );
+ const gateway = createMockGateway( {
+ state: { ...enabledGatewayState, enabled: false },
+ } );
+ const { queryByText } = render(
+ <PaymentGatewayListItem
+ gateway={ gateway }
+ { ...defaultProps }
+ />
+ );
+
+ expect(
+ queryByText( 'Limited compatibility' )
+ ).not.toBeInTheDocument();
+ } );
+
+ it( 'does not show the badge when no compatibility data is preloaded', () => {
+ const gateway = createMockGateway( {
+ state: enabledGatewayState,
+ } );
+ const { queryByText } = render(
+ <PaymentGatewayListItem
+ gateway={ gateway }
+ { ...defaultProps }
+ />
+ );
+
+ expect(
+ queryByText( 'Limited compatibility' )
+ ).not.toBeInTheDocument();
+ } );
+ } );
+
describe( 'Badge Rendering', () => {
it( 'shows OfficialBadge when _suggestion_id exists', () => {
const gateway = createMockGateway( {
diff --git a/plugins/woocommerce/client/admin/client/typings/global.d.ts b/plugins/woocommerce/client/admin/client/typings/global.d.ts
index ace9d9b9249..2a970a228ab 100644
--- a/plugins/woocommerce/client/admin/client/typings/global.d.ts
+++ b/plugins/woocommerce/client/admin/client/typings/global.d.ts
@@ -78,6 +78,9 @@ declare global {
woocommerce_payments_nox_profile?: {
business_country_code: string;
};
+ woocommerce_checkout_block_compatibility?: {
+ incompatible_gateway_ids: string[];
+ };
wcpay_welcome_page_connect_nonce: string;
currentUserData: {
first_name: string;
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsController.php b/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsController.php
index f8941344fc3..e9cac7ce279 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsController.php
+++ b/plugins/woocommerce/src/Internal/Admin/Settings/PaymentsController.php
@@ -3,6 +3,9 @@ declare( strict_types=1 );
namespace Automattic\WooCommerce\Internal\Admin\Settings;
+use Automattic\WooCommerce\Blocks\Package as BlocksPackage;
+use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
+use Automattic\WooCommerce\Blocks\Utils\CartCheckoutUtils;
use Automattic\WooCommerce\Internal\Admin\Settings\PaymentsProviders\WooPayments\WooPaymentsService;
use Automattic\WooCommerce\Internal\Logging\SafeGlobalFunctionProxy;
use Throwable;
@@ -147,9 +150,41 @@ class PaymentsController {
}
$settings[ Payments::PAYMENTS_NOX_PROFILE_KEY ]['business_country_code'] = $this->payments->get_country();
+ global $current_tab;
+
+ // Add the gateways that are not available in the Checkout block, but only when the store uses it.
+ if ( 'checkout' === $current_tab && CartCheckoutUtils::is_checkout_block_default() ) {
+ $settings['woocommerce_checkout_block_compatibility'] = array(
+ 'incompatible_gateway_ids' => $this->get_gateway_ids_incompatible_with_checkout_block(),
+ );
+ }
+
return $settings;
}
+ /**
+ * Get the IDs of the payment gateways that have no Checkout block payment method integration.
+ *
+ * The enabled state of the gateways is not taken into account.
+ *
+ * Matching is by integration name: a gateway counts as compatible when a registered
+ * Checkout block payment method integration has the same name as the gateway ID.
+ * Integrations registered only on the front end are not visible here, so their gateways are listed too.
+ *
+ * @return string[] The list of gateway IDs.
+ */
+ private function get_gateway_ids_incompatible_with_checkout_block(): array {
+ $registered_payment_method_names = array_map(
+ static fn( $payment_method ) => $payment_method->get_name(),
+ BlocksPackage::container()->get( PaymentMethodRegistry::class )->get_all_registered()
+ );
+
+ // `payment_gateways()` is keyed by gateway ID; pluck the IDs as a plain list for the diff below.
+ $gateway_ids = wp_list_pluck( WC()->payment_gateways()->payment_gateways(), 'id' );
+
+ return array_values( array_diff( $gateway_ids, $registered_payment_method_names ) );
+ }
+
/**
* Adds promo note IDs to the list of allowed ones.
*
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsControllerTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsControllerTest.php
new file mode 100644
index 00000000000..315d12fbf4e
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/Settings/PaymentsControllerTest.php
@@ -0,0 +1,259 @@
+<?php
+declare( strict_types=1 );
+
+namespace Automattic\WooCommerce\Tests\Internal\Admin\Settings;
+
+use Automattic\WooCommerce\Blocks\Package as BlocksPackage;
+use Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType;
+use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
+use Automattic\WooCommerce\Internal\Admin\Settings\PaymentsController;
+use Automattic\WooCommerce\Tests\Internal\Admin\Settings\Mocks\FakePaymentGateway;
+use WC_Unit_Test_Case;
+
+/**
+ * Tests for the PaymentsController class.
+ */
+class PaymentsControllerTest extends WC_Unit_Test_Case {
+
+ /**
+ * The System Under Test.
+ *
+ * @var PaymentsController
+ */
+ private $sut;
+
+ /**
+ * The ID of the checkout page created for the test.
+ *
+ * @var int
+ */
+ private $checkout_page_id;
+
+ /**
+ * The callback used to register the fake gateway, if any.
+ *
+ * @var callable|null
+ */
+ private $gateways_filter_callback = null;
+
+ /**
+ * The names of the Checkout block payment method integrations registered by the test.
+ *
+ * @var string[]
+ */
+ private $registered_integration_names = array();
+
+ /**
+ * Set up test fixtures.
+ */
+ public function setUp(): void {
+ parent::setUp();
+
+ set_current_screen( 'woocommerce_page_wc-settings' );
+ $GLOBALS['current_tab'] = 'checkout';
+
+ $this->checkout_page_id = $this->factory->post->create(
+ array(
+ 'post_type' => 'page',
+ 'post_content' => '<!-- wp:woocommerce/checkout --><!-- /wp:woocommerce/checkout -->',
+ )
+ );
+ update_option( 'woocommerce_checkout_page_id', $this->checkout_page_id );
+
+ $this->sut = wc_get_container()->get( PaymentsController::class );
+ }
+
+ /**
+ * Tear down test fixtures.
+ */
+ public function tearDown(): void {
+ unset( $GLOBALS['current_tab'] );
+ set_current_screen( 'front' );
+
+ if ( null !== $this->gateways_filter_callback ) {
+ remove_filter( 'woocommerce_payment_gateways', $this->gateways_filter_callback );
+ $this->gateways_filter_callback = null;
+ }
+ WC()->payment_gateways()->payment_gateways = array();
+ WC()->payment_gateways()->init();
+
+ foreach ( $this->registered_integration_names as $name ) {
+ if ( $this->get_payment_method_registry()->is_registered( $name ) ) {
+ $this->get_payment_method_registry()->unregister( $name );
+ }
+ }
+ $this->registered_integration_names = array();
+
+ parent::tearDown();
+ }
+
+ /**
+ * @testdox Should list gateways that have no Checkout block payment method integration.
+ */
+ public function test_preload_settings_lists_gateways_without_a_checkout_block_integration(): void {
+ $this->register_fake_gateway();
+ $this->register_fake_block_payment_integration( 'other-fake-gateway-id' );
+
+ $settings = $this->sut->preload_settings();
+
+ $this->assertContains(
+ 'fake-gateway-id',
+ $settings['woocommerce_checkout_block_compatibility']['incompatible_gateway_ids'],
+ 'A gateway without a Checkout block integration should be reported as incompatible'
+ );
+ }
+
+ /**
+ * @testdox Should not list gateways that have a Checkout block payment method integration.
+ */
+ public function test_preload_settings_skips_gateways_with_a_checkout_block_integration(): void {
+ $this->register_fake_gateway();
+ $this->register_fake_block_payment_integration( 'fake-gateway-id' );
+
+ $settings = $this->sut->preload_settings();
+
+ $this->assertNotContains(
+ 'fake-gateway-id',
+ $settings['woocommerce_checkout_block_compatibility']['incompatible_gateway_ids'],
+ 'A gateway with a Checkout block integration should not be reported as incompatible'
+ );
+ }
+
+ /**
+ * @testdox Should list incompatible gateways regardless of them being enabled.
+ */
+ public function test_preload_settings_lists_incompatible_gateways_that_are_disabled(): void {
+ $this->register_fake_gateway( 'no' );
+ $this->register_fake_block_payment_integration( 'other-fake-gateway-id' );
+
+ $settings = $this->sut->preload_settings();
+
+ $this->assertContains(
+ 'fake-gateway-id',
+ $settings['woocommerce_checkout_block_compatibility']['incompatible_gateway_ids'],
+ 'The enabled state of a gateway should not influence the compatibility list'
+ );
+ }
+
+ /**
+ * @testdox Should not add compatibility data when the checkout page does not use the Checkout block.
+ */
+ public function test_preload_settings_adds_no_compatibility_data_for_the_classic_checkout(): void {
+ wp_update_post(
+ array(
+ 'ID' => $this->checkout_page_id,
+ 'post_content' => '<!-- wp:shortcode -->[woocommerce_checkout]<!-- /wp:shortcode -->',
+ )
+ );
+ $this->register_fake_gateway();
+
+ $settings = $this->sut->preload_settings();
+
+ $this->assertArrayNotHasKey(
+ 'woocommerce_checkout_block_compatibility',
+ $settings,
+ 'Stores on the classic checkout should not receive compatibility data'
+ );
+ }
+
+ /**
+ * @testdox Should not add compatibility data outside of the payments settings tab.
+ */
+ public function test_preload_settings_adds_no_compatibility_data_outside_the_payments_tab(): void {
+ $GLOBALS['current_tab'] = 'general';
+ $this->register_fake_gateway();
+
+ $settings = $this->sut->preload_settings();
+
+ $this->assertArrayNotHasKey(
+ 'woocommerce_checkout_block_compatibility',
+ $settings,
+ 'Compatibility data is only needed by the payments settings page'
+ );
+ }
+
+ /**
+ * @testdox Should not list gateways whose Checkout block integration only sets its name in initialize().
+ */
+ public function test_preload_settings_skips_gateways_whose_integration_is_named_on_initialize(): void {
+ $this->register_fake_gateway();
+
+ // Like WooPayments: `$name` stays at the default '' when the registry keys it in register(),
+ // and is only assigned once initialize() runs.
+ $integration = new class() extends AbstractPaymentMethodType {
+ /**
+ * Initializes the payment method type.
+ */
+ public function initialize() {
+ $this->name = 'fake-gateway-id';
+ }
+ };
+
+ $this->get_payment_method_registry()->register( $integration );
+ $integration->initialize();
+
+ // The registry keyed it under the default empty name, so that is what teardown must unregister.
+ $this->registered_integration_names[] = '';
+
+ $settings = $this->sut->preload_settings();
+
+ $this->assertNotContains(
+ 'fake-gateway-id',
+ $settings['woocommerce_checkout_block_compatibility']['incompatible_gateway_ids'],
+ 'A gateway whose integration only sets its name in initialize() should not be reported as incompatible'
+ );
+ }
+
+ /**
+ * Add a gateway without a Checkout block integration to the list of loaded gateways.
+ *
+ * @param string $enabled Whether the gateway is enabled: 'yes' or 'no'.
+ */
+ private function register_fake_gateway( string $enabled = 'yes' ): void {
+ $this->gateways_filter_callback = function ( $gateways ) use ( $enabled ) {
+ $gateway = new FakePaymentGateway();
+ $gateway->enabled = $enabled;
+ $gateways[] = $gateway;
+
+ return $gateways;
+ };
+ add_filter( 'woocommerce_payment_gateways', $this->gateways_filter_callback );
+
+ WC()->payment_gateways()->init();
+ }
+
+ /**
+ * Register a minimal Checkout block payment method integration.
+ *
+ * @param string $name The integration name, matching the gateway ID it stands for.
+ */
+ private function register_fake_block_payment_integration( string $name ): void {
+ $integration = new class( $name ) extends AbstractPaymentMethodType {
+ /**
+ * Constructor.
+ *
+ * @param string $name The integration name.
+ */
+ public function __construct( string $name ) {
+ $this->name = $name;
+ }
+
+ /**
+ * Initializes the payment method type.
+ */
+ public function initialize() {}
+ };
+
+ $this->get_payment_method_registry()->register( $integration );
+ $this->registered_integration_names[] = $name;
+ }
+
+ /**
+ * Get the Checkout block payment method registry.
+ *
+ * @return PaymentMethodRegistry
+ */
+ private function get_payment_method_registry(): PaymentMethodRegistry {
+ return BlocksPackage::container()->get( PaymentMethodRegistry::class );
+ }
+}