Commit 0fc02aa827a for woocommerce
commit 0fc02aa827a813a790d4c8820aec21158f9c8a61
Author: Luigi Teschio <gigitux@gmail.com>
Date: Wed Jul 15 13:25:45 2026 +0200
Fix client-only blocks disappearing from the post editor (#66628)
* Fix client-only blocks disappearing from post editor
* Add changelog entry for block editor deny-list fix
diff --git a/plugins/woocommerce/changelog/fix-66612-block-editor-deny-list b/plugins/woocommerce/changelog/fix-66612-block-editor-deny-list
new file mode 100644
index 00000000000..b649992ea7e
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-66612-block-editor-deny-list
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prevent client-side-only blocks from disappearing from the post editor inserter.
diff --git a/plugins/woocommerce/client/blocks/assets/js/filters/unregister-block-types/block-types.ts b/plugins/woocommerce/client/blocks/assets/js/filters/unregister-block-types/block-types.ts
new file mode 100644
index 00000000000..f332fcc5c47
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/assets/js/filters/unregister-block-types/block-types.ts
@@ -0,0 +1,78 @@
+/**
+ * WooCommerce block types hidden from post editors.
+ */
+export const POST_EDITOR_BLOCK_TYPES_TO_UNREGISTER = [
+ 'woocommerce/breadcrumbs',
+ 'woocommerce/catalog-sorting',
+ 'woocommerce/legacy-template',
+ 'woocommerce/product-results-count',
+ 'woocommerce/product-reviews',
+ 'woocommerce/order-confirmation-status',
+ 'woocommerce/order-confirmation-summary',
+ 'woocommerce/order-confirmation-totals',
+ 'woocommerce/order-confirmation-totals-wrapper',
+ 'woocommerce/order-confirmation-downloads',
+ 'woocommerce/order-confirmation-downloads-wrapper',
+ 'woocommerce/order-confirmation-billing-address',
+ 'woocommerce/order-confirmation-shipping-address',
+ 'woocommerce/order-confirmation-billing-wrapper',
+ 'woocommerce/order-confirmation-shipping-wrapper',
+ 'woocommerce/order-confirmation-additional-information',
+ 'woocommerce/order-confirmation-additional-fields-wrapper',
+ 'woocommerce/order-confirmation-additional-fields',
+];
+
+/**
+ * WooCommerce block types allowed in Widget Areas. New blocks won't be
+ * exposed in the Widget Area unless specifically added here.
+ */
+export const WIDGET_EDITOR_ALLOWED_BLOCK_TYPES = [
+ 'woocommerce/all-reviews',
+ 'woocommerce/breadcrumbs',
+ 'woocommerce/cart-link',
+ 'woocommerce/catalog-sorting',
+ 'woocommerce/classic-shortcode',
+ 'woocommerce/customer-account',
+ 'woocommerce/dropdown',
+ 'woocommerce/featured-category',
+ 'woocommerce/featured-product',
+ 'woocommerce/mini-cart',
+ 'woocommerce/product-categories',
+ 'woocommerce/product-results-count',
+ 'woocommerce/product-search',
+ 'woocommerce/reviews-by-category',
+ 'woocommerce/reviews-by-product',
+ 'woocommerce/product-filters',
+ 'woocommerce/product-filter-status',
+ 'woocommerce/product-filter-price',
+ 'woocommerce/product-filter-price-slider',
+ 'woocommerce/product-filter-attribute',
+ 'woocommerce/product-filter-rating',
+ 'woocommerce/product-filter-active',
+ 'woocommerce/product-filter-removable-chips',
+ 'woocommerce/product-filter-clear-button',
+ 'woocommerce/product-filter-checkbox-list',
+ 'woocommerce/product-filter-chips',
+ 'woocommerce/product-filter-taxonomy',
+
+ // Keep hidden legacy filter blocks for backward compatibility.
+ 'woocommerce/active-filters',
+ 'woocommerce/attribute-filter',
+ 'woocommerce/filter-wrapper',
+ 'woocommerce/price-filter',
+ 'woocommerce/rating-filter',
+ 'woocommerce/stock-filter',
+ // End: legacy filter blocks.
+
+ // Below product grids are hidden from inserter however they could have been used in widgets.
+ // Keep them for backward compatibility.
+ 'woocommerce/handpicked-products',
+ 'woocommerce/product-best-sellers',
+ 'woocommerce/product-new',
+ 'woocommerce/product-on-sale',
+ 'woocommerce/product-top-rated',
+ 'woocommerce/products-by-attribute',
+ 'woocommerce/product-category',
+ 'woocommerce/product-tag',
+ // End: legacy product grids blocks.
+];
diff --git a/plugins/woocommerce/client/blocks/assets/js/filters/unregister-block-types/index.ts b/plugins/woocommerce/client/blocks/assets/js/filters/unregister-block-types/index.ts
new file mode 100644
index 00000000000..29ea6d297c4
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/assets/js/filters/unregister-block-types/index.ts
@@ -0,0 +1,56 @@
+/**
+ * External dependencies
+ */
+import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
+import domReady from '@wordpress/dom-ready';
+
+/**
+ * Internal dependencies
+ */
+import {
+ POST_EDITOR_BLOCK_TYPES_TO_UNREGISTER,
+ WIDGET_EDITOR_ALLOWED_BLOCK_TYPES,
+} from './block-types';
+
+type BlockEditorContext = 'post' | 'widgets' | 'other';
+
+const getBlockEditorContext = (): BlockEditorContext => {
+ const adminPage = ( window as Window & { adminpage?: string } ).adminpage;
+
+ if ( [ 'post-php', 'post-new-php' ].includes( adminPage ?? '' ) ) {
+ return 'post';
+ }
+
+ if ( [ 'widgets-php', 'customize-php' ].includes( adminPage ?? '' ) ) {
+ return 'widgets';
+ }
+
+ return 'other';
+};
+
+const getBlockTypesToUnregister = (): string[] => {
+ const registeredBlockTypes = getBlockTypes().map( ( { name } ) => name );
+ const blockEditorContext = getBlockEditorContext();
+
+ if ( blockEditorContext === 'post' ) {
+ return POST_EDITOR_BLOCK_TYPES_TO_UNREGISTER.filter( ( blockType ) =>
+ registeredBlockTypes.includes( blockType )
+ );
+ }
+
+ if ( blockEditorContext === 'widgets' ) {
+ return registeredBlockTypes.filter(
+ ( blockType ) =>
+ blockType.startsWith( 'woocommerce/' ) &&
+ ! WIDGET_EDITOR_ALLOWED_BLOCK_TYPES.includes( blockType )
+ );
+ }
+
+ return [];
+};
+
+domReady( () => {
+ getBlockTypesToUnregister().forEach( ( blockType ) => {
+ unregisterBlockType( blockType );
+ } );
+} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/filters/unregister-block-types/test/index.ts b/plugins/woocommerce/client/blocks/assets/js/filters/unregister-block-types/test/index.ts
new file mode 100644
index 00000000000..cacce94f0c6
--- /dev/null
+++ b/plugins/woocommerce/client/blocks/assets/js/filters/unregister-block-types/test/index.ts
@@ -0,0 +1,104 @@
+/**
+ * External dependencies
+ */
+import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
+
+jest.mock( '@wordpress/blocks', () => ( {
+ getBlockTypes: jest.fn(),
+ unregisterBlockType: jest.fn(),
+} ) );
+
+jest.mock( '@wordpress/dom-ready', () => ( {
+ __esModule: true,
+ default: jest.fn( ( callback ) => callback() ),
+} ) );
+
+const loadFilter = ( adminPage: string | undefined, blockTypes: string[] ) => {
+ ( window as Window & { adminpage?: string } ).adminpage = adminPage;
+ ( getBlockTypes as jest.Mock ).mockReturnValue(
+ blockTypes.map( ( name ) => ( { name } ) )
+ );
+
+ jest.isolateModules( () => {
+ require( '../index' );
+ } );
+};
+
+describe( 'unregister block types', () => {
+ beforeEach( () => {
+ jest.clearAllMocks();
+ } );
+
+ it.each( [ 'post-php', 'post-new-php' ] )(
+ 'unregisters only post-editor block types in the deny list in %s',
+ ( adminPage ) => {
+ loadFilter( adminPage, [
+ 'woocommerce/breadcrumbs',
+ 'woocommerce/product-reviews',
+ 'woocommerce/product-search',
+ 'myplugin/client-only',
+ ] );
+
+ expect( unregisterBlockType ).toHaveBeenCalledTimes( 2 );
+ expect( unregisterBlockType ).toHaveBeenCalledWith(
+ 'woocommerce/breadcrumbs'
+ );
+ expect( unregisterBlockType ).toHaveBeenCalledWith(
+ 'woocommerce/product-reviews'
+ );
+ expect( unregisterBlockType ).not.toHaveBeenCalledWith(
+ 'woocommerce/product-search'
+ );
+ expect( unregisterBlockType ).not.toHaveBeenCalledWith(
+ 'myplugin/client-only'
+ );
+ }
+ );
+
+ it.each( [ 'widgets-php', 'customize-php' ] )(
+ 'unregisters WooCommerce blocks outside the widget-editor allow list in %s',
+ ( context ) => {
+ loadFilter( context, [
+ 'woocommerce/product-search',
+ 'woocommerce/product-filters',
+ 'woocommerce/checkout',
+ 'woocommerce/order-confirmation-status',
+ 'woocommerce/new-widget-compatible-block',
+ 'myplugin/client-only',
+ ] );
+
+ expect( unregisterBlockType ).toHaveBeenCalledTimes( 3 );
+ expect( unregisterBlockType ).toHaveBeenCalledWith(
+ 'woocommerce/checkout'
+ );
+ expect( unregisterBlockType ).toHaveBeenCalledWith(
+ 'woocommerce/order-confirmation-status'
+ );
+ expect( unregisterBlockType ).not.toHaveBeenCalledWith(
+ 'woocommerce/product-search'
+ );
+ expect( unregisterBlockType ).not.toHaveBeenCalledWith(
+ 'woocommerce/product-filters'
+ );
+ expect( unregisterBlockType ).toHaveBeenCalledWith(
+ 'woocommerce/new-widget-compatible-block'
+ );
+ expect( unregisterBlockType ).not.toHaveBeenCalledWith(
+ 'myplugin/client-only'
+ );
+ }
+ );
+
+ it.each( [ 'site-editor-php', undefined ] )(
+ 'does not unregister blocks in unrestricted editor contexts (%s)',
+ ( adminPage ) => {
+ loadFilter( adminPage, [
+ 'woocommerce/breadcrumbs',
+ 'woocommerce/checkout',
+ 'myplugin/client-only',
+ ] );
+
+ expect( unregisterBlockType ).not.toHaveBeenCalled();
+ }
+ );
+} );
diff --git a/plugins/woocommerce/client/blocks/assets/js/index.js b/plugins/woocommerce/client/blocks/assets/js/index.js
index eef34acb45a..d481cda11f1 100644
--- a/plugins/woocommerce/client/blocks/assets/js/index.js
+++ b/plugins/woocommerce/client/blocks/assets/js/index.js
@@ -5,4 +5,5 @@ import '../css/editor.scss';
import '../css/style.scss';
import './filters/block-list-block';
import './filters/get-block-attributes';
+import './filters/unregister-block-types';
import './base/components/notice-banner/style.scss';
diff --git a/plugins/woocommerce/src/Blocks/BlockTypesController.php b/plugins/woocommerce/src/Blocks/BlockTypesController.php
index b9db30d3e9d..db68a52932b 100644
--- a/plugins/woocommerce/src/Blocks/BlockTypesController.php
+++ b/plugins/woocommerce/src/Blocks/BlockTypesController.php
@@ -62,7 +62,6 @@ final class BlockTypesController {
add_filter( 'render_block', array( $this, 'add_data_attributes' ), 10, 2 );
add_action( 'woocommerce_login_form_end', array( $this, 'redirect_to_field' ) );
add_filter( 'widget_types_to_hide_from_legacy_widget_block', array( $this, 'hide_legacy_widgets_with_block_equivalent' ) );
- add_filter( 'allowed_block_types_all', array( $this, 'filter_allowed_block_types' ), 10, 2 );
add_filter( 'register_block_type_args', array( $this, 'enqueue_block_style_for_classic_themes' ), 10, 2 );
add_filter( 'block_core_breadcrumbs_post_type_settings', array( $this, 'set_product_breadcrumbs_preferred_taxonomy' ), 10, 3 );
add_filter( 'block_core_breadcrumbs_items', array( $this, 'apply_woocommerce_breadcrumb_filters' ), 10, 1 );
@@ -359,80 +358,6 @@ final class BlockTypesController {
return $widget_types;
}
- /**
- * Filter WooCommerce block availability by editor context.
- *
- * Blocks remain registered on the server for compatibility, but some WooCommerce
- * blocks are hidden from specific editor inserters.
- *
- * @param bool|string[] $allowed_block_types Array of block type slugs, or boolean to enable/disable all.
- * @param \WP_Block_Editor_Context $block_editor_context The current block editor context.
- * @return bool|string[] Filtered list of allowed block types, or boolean to enable/disable all.
- */
- public function filter_allowed_block_types( $allowed_block_types, $block_editor_context ) {
- if ( false === $allowed_block_types ) {
- return false;
- }
-
- $editor_name = $block_editor_context->name;
-
- if ( 'core/edit-site' === $editor_name ) {
- return $allowed_block_types;
- }
-
- if ( 'core/edit-post' === $editor_name ) {
- return $this->remove_allowed_block_types(
- $allowed_block_types,
- $this->get_post_editor_hidden_block_types()
- );
- }
-
- if ( in_array( $editor_name, array( 'core/edit-widgets', 'core/customize-widgets' ), true ) ) {
- $registered_block_types = $this->get_registered_block_types();
- $registered_woocommerce_block_types = array_filter(
- $registered_block_types,
- static function ( $block_type ) {
- return 0 === strpos( $block_type, 'woocommerce/' );
- }
- );
-
- return $this->remove_allowed_block_types(
- $allowed_block_types,
- array_diff( $registered_woocommerce_block_types, $this->get_widget_area_block_types() )
- );
- }
-
- return $allowed_block_types;
- }
-
- /**
- * Remove block types from the current allowed block list.
- *
- * @param bool|string[] $allowed_block_types Array of block type slugs, or true to allow all registered block types.
- * @param string[] $block_types_to_remove Block type slugs to remove.
- * @return string[] Filtered block type slugs.
- */
- private function remove_allowed_block_types( $allowed_block_types, array $block_types_to_remove ) {
- $allowed_block_types = true === $allowed_block_types ? $this->get_registered_block_types() : (array) $allowed_block_types;
- $allowed_block_types = array_filter( $allowed_block_types, 'is_string' );
-
- return array_values(
- array_diff(
- $allowed_block_types,
- $block_types_to_remove
- )
- );
- }
-
- /**
- * Get all registered block type slugs.
- *
- * @return string[] Registered block type slugs.
- */
- private function get_registered_block_types() {
- return array_keys( \WP_Block_Type_Registry::get_instance()->get_all_registered() );
- }
-
/**
* Delete product transients when a product is deleted.
*
@@ -443,93 +368,6 @@ final class BlockTypesController {
wc_deprecated_function( __METHOD__, '10.6.0' );
}
- /**
- * Get list of WooCommerce block types allowed in Widget Areas. New blocks won't be
- * exposed in the Widget Area unless specifically added here.
- *
- * @return string[] Array of block type slugs.
- */
- protected function get_widget_area_block_types() {
- return array(
- 'woocommerce/all-reviews',
- 'woocommerce/breadcrumbs',
- 'woocommerce/cart-link',
- 'woocommerce/catalog-sorting',
- 'woocommerce/classic-shortcode',
- 'woocommerce/customer-account',
- 'woocommerce/dropdown',
- 'woocommerce/featured-category',
- 'woocommerce/featured-product',
- 'woocommerce/mini-cart',
- 'woocommerce/product-categories',
- 'woocommerce/product-results-count',
- 'woocommerce/product-search',
- 'woocommerce/reviews-by-category',
- 'woocommerce/reviews-by-product',
- 'woocommerce/product-filters',
- 'woocommerce/product-filter-status',
- 'woocommerce/product-filter-price',
- 'woocommerce/product-filter-price-slider',
- 'woocommerce/product-filter-attribute',
- 'woocommerce/product-filter-rating',
- 'woocommerce/product-filter-active',
- 'woocommerce/product-filter-removable-chips',
- 'woocommerce/product-filter-clear-button',
- 'woocommerce/product-filter-checkbox-list',
- 'woocommerce/product-filter-chips',
- 'woocommerce/product-filter-taxonomy',
-
- // Keep hidden legacy filter blocks for backward compatibility.
- 'woocommerce/active-filters',
- 'woocommerce/attribute-filter',
- 'woocommerce/filter-wrapper',
- 'woocommerce/price-filter',
- 'woocommerce/rating-filter',
- 'woocommerce/stock-filter',
- // End: legacy filter blocks.
-
- // Below product grids are hidden from inserter however they could have been used in widgets.
- // Keep them for backward compatibility.
- 'woocommerce/handpicked-products',
- 'woocommerce/product-best-sellers',
- 'woocommerce/product-new',
- 'woocommerce/product-on-sale',
- 'woocommerce/product-top-rated',
- 'woocommerce/products-by-attribute',
- 'woocommerce/product-category',
- 'woocommerce/product-tag',
- // End: legacy product grids blocks.
- );
- }
-
- /**
- * Get list of WooCommerce block types hidden from post editors.
- *
- * @return string[] Array of block type slugs.
- */
- protected function get_post_editor_hidden_block_types() {
- return array(
- 'woocommerce/breadcrumbs',
- 'woocommerce/catalog-sorting',
- 'woocommerce/legacy-template',
- 'woocommerce/product-results-count',
- 'woocommerce/product-reviews',
- 'woocommerce/order-confirmation-status',
- 'woocommerce/order-confirmation-summary',
- 'woocommerce/order-confirmation-totals',
- 'woocommerce/order-confirmation-totals-wrapper',
- 'woocommerce/order-confirmation-downloads',
- 'woocommerce/order-confirmation-downloads-wrapper',
- 'woocommerce/order-confirmation-billing-address',
- 'woocommerce/order-confirmation-shipping-address',
- 'woocommerce/order-confirmation-billing-wrapper',
- 'woocommerce/order-confirmation-shipping-wrapper',
- 'woocommerce/order-confirmation-additional-information',
- 'woocommerce/order-confirmation-additional-fields-wrapper',
- 'woocommerce/order-confirmation-additional-fields',
- );
- }
-
/**
* Get list of block types.
*
diff --git a/plugins/woocommerce/tests/php/src/Blocks/BlockTypesController.php b/plugins/woocommerce/tests/php/src/Blocks/BlockTypesController.php
index 515fb607586..b75082a26fd 100644
--- a/plugins/woocommerce/tests/php/src/Blocks/BlockTypesController.php
+++ b/plugins/woocommerce/tests/php/src/Blocks/BlockTypesController.php
@@ -20,13 +20,6 @@ class BlockTypesController extends \WP_UnitTestCase {
*/
private $block_types_controller;
- /**
- * Block types registered during a test.
- *
- * @var string[]
- */
- private $registered_test_block_types = array();
-
/**
* Sets up a new TestedBlockTypesController so it can be tested.
*
@@ -41,23 +34,6 @@ class BlockTypesController extends \WP_UnitTestCase {
);
}
- /**
- * Tear down test fixtures.
- */
- public function tearDown(): void {
- foreach ( $this->registered_test_block_types as $block_type ) {
- if ( \WP_Block_Type_Registry::get_instance()->is_registered( $block_type ) ) {
- unregister_block_type( $block_type );
- }
- }
-
- $this->registered_test_block_types = array();
-
- remove_filter( 'allowed_block_types_all', array( $this->block_types_controller, 'filter_allowed_block_types' ), 10 );
-
- parent::tearDown();
- }
-
/**
* Register 3 blocks, one will be allowed by full name, one by namespace,and one because it has a parent with a
* woocommerce namespace.
@@ -118,210 +94,4 @@ class BlockTypesController extends \WP_UnitTestCase {
$answer = $this->block_types_controller->block_should_have_data_attributes( 'child-of-woo/block-name' );
$this->assertTrue( $answer );
}
-
- /**
- * @testdox Should hide post-editor WooCommerce blocks from unrestricted post editors.
- */
- public function test_edit_post_context_hides_post_editor_block_types_from_unrestricted_list(): void {
- foreach (
- array(
- 'core/test-paragraph',
- 'third-party/test-block',
- 'woocommerce/product-search',
- 'woocommerce/breadcrumbs',
- 'woocommerce/product-reviews',
- 'woocommerce/order-confirmation-status',
- ) as $block_type
- ) {
- $this->register_test_block_type( $block_type );
- }
-
- $result = $this->block_types_controller->filter_allowed_block_types(
- true,
- $this->get_block_editor_context( 'core/edit-post' )
- );
-
- $this->assertContains( 'core/test-paragraph', $result, 'Non-WooCommerce blocks should remain available.' );
- $this->assertContains( 'third-party/test-block', $result, 'Third-party blocks should remain available.' );
- $this->assertContains( 'woocommerce/product-search', $result, 'WooCommerce blocks outside the denylist should remain available.' );
- $this->assertNotContains( 'woocommerce/breadcrumbs', $result, 'Store Breadcrumbs should be hidden in post editors.' );
- $this->assertNotContains( 'woocommerce/product-reviews', $result, 'Product Reviews should be hidden in post editors.' );
- $this->assertNotContains( 'woocommerce/order-confirmation-status', $result, 'Order Confirmation blocks should be hidden in post editors.' );
- }
-
- /**
- * @testdox Should keep only widget-area WooCommerce blocks in widget editors.
- *
- * @dataProvider widget_editor_context_provider
- *
- * @param string $editor_context_name Editor context name.
- */
- public function test_widget_context_hides_woocommerce_blocks_not_allowed_in_widget_areas( string $editor_context_name ): void {
- foreach (
- array(
- 'core/test-paragraph',
- 'third-party/test-block',
- 'woocommerce/product-search',
- 'woocommerce/product-filters',
- 'woocommerce/checkout',
- 'woocommerce/order-confirmation-status',
- ) as $block_type
- ) {
- $this->register_test_block_type( $block_type );
- }
-
- $result = $this->block_types_controller->filter_allowed_block_types(
- true,
- $this->get_block_editor_context( $editor_context_name )
- );
-
- $this->assertContains( 'core/test-paragraph', $result, 'Non-WooCommerce blocks should remain available.' );
- $this->assertContains( 'third-party/test-block', $result, 'Third-party blocks should remain available.' );
- $this->assertContains( 'woocommerce/product-search', $result, 'Widget-area WooCommerce blocks should remain available.' );
- $this->assertContains( 'woocommerce/product-filters', $result, 'Widget-area WooCommerce blocks should remain available.' );
- $this->assertNotContains( 'woocommerce/checkout', $result, 'WooCommerce blocks outside the widget allowlist should be hidden.' );
- $this->assertNotContains( 'woocommerce/order-confirmation-status', $result, 'WooCommerce blocks outside the widget allowlist should be hidden.' );
- }
-
- /**
- * @testdox Should leave Site Editor block availability unchanged.
- */
- public function test_site_editor_context_leaves_allowed_block_types_unchanged(): void {
- $allowed_block_types = array(
- 'core/test-paragraph',
- 'woocommerce/breadcrumbs',
- 'woocommerce/checkout',
- );
-
- $result = $this->block_types_controller->filter_allowed_block_types(
- $allowed_block_types,
- $this->get_block_editor_context( 'core/edit-site' )
- );
-
- $this->assertSame( $allowed_block_types, $result, 'Site Editor block availability should not be changed.' );
- }
-
- /**
- * @testdox Should preserve an existing post editor allowlist while removing denied WooCommerce blocks.
- */
- public function test_edit_post_context_preserves_existing_allowlist(): void {
- $allowed_block_types = array(
- 'core/test-paragraph',
- 'woocommerce/product-search',
- 'woocommerce/catalog-sorting',
- 'third-party/test-block',
- );
-
- $result = $this->block_types_controller->filter_allowed_block_types(
- $allowed_block_types,
- $this->get_block_editor_context( 'core/edit-post' )
- );
-
- $this->assertSame(
- array(
- 'core/test-paragraph',
- 'woocommerce/product-search',
- 'third-party/test-block',
- ),
- $result,
- 'Existing allowlists should keep their original restrictions.'
- );
- }
-
- /**
- * @testdox Should preserve an existing widget editor allowlist while removing disallowed WooCommerce blocks.
- */
- public function test_widget_context_preserves_existing_allowlist(): void {
- $allowed_block_types = array(
- 'core/test-paragraph',
- 'woocommerce/product-search',
- 'woocommerce/checkout',
- 'third-party/test-block',
- );
-
- $result = $this->block_types_controller->filter_allowed_block_types(
- $allowed_block_types,
- $this->get_block_editor_context( 'core/edit-widgets' )
- );
-
- $this->assertSame(
- array(
- 'core/test-paragraph',
- 'woocommerce/product-search',
- 'third-party/test-block',
- ),
- $result,
- 'Existing allowlists should keep their original restrictions.'
- );
- }
-
- /**
- * @testdox Should preserve false block availability for restricted editors.
- *
- * @dataProvider restricted_editor_context_provider
- *
- * @param string $editor_context_name Editor context name.
- */
- public function test_restricted_context_preserves_false_allowed_block_types( string $editor_context_name ): void {
- $result = $this->block_types_controller->filter_allowed_block_types(
- false,
- $this->get_block_editor_context( $editor_context_name )
- );
-
- $this->assertFalse( $result, 'Existing disabled block availability should be preserved.' );
- }
-
- /**
- * Data provider for widget editor contexts.
- *
- * @return array<string, array<string>>
- */
- public function widget_editor_context_provider(): array {
- return array(
- 'widgets editor' => array( 'core/edit-widgets' ),
- 'customizer editor' => array( 'core/customize-widgets' ),
- );
- }
-
- /**
- * Data provider for restricted editor contexts.
- *
- * @return array<string, array<string>>
- */
- public function restricted_editor_context_provider(): array {
- return array(
- 'post editor' => array( 'core/edit-post' ),
- 'widgets editor' => array( 'core/edit-widgets' ),
- 'customizer editor' => array( 'core/customize-widgets' ),
- );
- }
-
- /**
- * Register a block type and track it for cleanup.
- *
- * @param string $block_type Block type slug.
- */
- private function register_test_block_type( string $block_type ): void {
- if ( \WP_Block_Type_Registry::get_instance()->is_registered( $block_type ) ) {
- return;
- }
-
- register_block_type( $block_type );
-
- $this->registered_test_block_types[] = $block_type;
- }
-
- /**
- * Get a block editor context for tests.
- *
- * @param string $editor_context_name Editor context name.
- * @return \WP_Block_Editor_Context Block editor context.
- */
- private function get_block_editor_context( string $editor_context_name ): \WP_Block_Editor_Context {
- return new \WP_Block_Editor_Context(
- array(
- 'name' => $editor_context_name,
- )
- );
- }
}