From 5095a4f50b42687a4b413cd732a48ccc7c4dc974 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 15 Jul 2026 11:09:02 +0100 Subject: [PATCH 1/2] Tests: Cover block content filter helper --- .../blocks/wpApplyBlockContentFilters.php | 262 ++++++++++++++++++ 1 file changed, 262 insertions(+) create mode 100644 tests/phpunit/tests/blocks/wpApplyBlockContentFilters.php diff --git a/tests/phpunit/tests/blocks/wpApplyBlockContentFilters.php b/tests/phpunit/tests/blocks/wpApplyBlockContentFilters.php new file mode 100644 index 0000000000000..c3ad1b7f06a77 --- /dev/null +++ b/tests/phpunit/tests/blocks/wpApplyBlockContentFilters.php @@ -0,0 +1,262 @@ +original_use_smilies = get_option( 'use_smilies' ); + $this->filtered_image_context = null; + + update_option( 'use_smilies', 1 ); + smilies_init(); + + register_block_type( + self::TEST_BLOCK_NAME, + array( + 'render_callback' => static function ( $attributes ) { + return sprintf( + '
%s
', + esc_html( $attributes['label'] ) + ); + }, + ) + ); + + register_block_type( + self::TEST_EXCEPTION_BLOCK_NAME, + array( + 'render_callback' => static function () { + throw new Exception( 'Block rendering failed.' ); + }, + ) + ); + } + + public function tear_down() { + remove_shortcode( self::TEST_SHORTCODE ); + wp_embed_unregister_handler( self::TEST_EMBED_HANDLER ); + remove_filter( 'wp_content_img_tag', array( $this, 'filter_content_image_tag' ) ); + + if ( WP_Block_Type_Registry::get_instance()->is_registered( self::TEST_BLOCK_NAME ) ) { + unregister_block_type( self::TEST_BLOCK_NAME ); + } + + if ( WP_Block_Type_Registry::get_instance()->is_registered( self::TEST_EXCEPTION_BLOCK_NAME ) ) { + unregister_block_type( self::TEST_EXCEPTION_BLOCK_NAME ); + } + + update_option( 'use_smilies', $this->original_use_smilies ); + + parent::tear_down(); + } + + /** + * Filters content image tags. + * + * @param string $filtered_image Full img tag with attributes. + * @param string $context Context for the image tag. + * @return string Filtered image tag. + */ + public function filter_content_image_tag( $filtered_image, $context ) { + $this->filtered_image_context = $context; + + if ( str_contains( $filtered_image, 'class="content-image"' ) ) { + return str_replace( 'Embedded content'; + } + + /** + * Tests that each expected content filter is applied. + * + * @ticket 65586 + */ + public function test_applies_content_filters() { + add_filter( 'wp_content_img_tag', array( $this, 'filter_content_image_tag' ), 10, 2 ); + + wp_embed_register_handler( + self::TEST_EMBED_HANDLER, + '#https?://example\.com/apply-block-content-filters#i', + array( $this, 'render_test_embed' ) + ); + + add_shortcode( + self::TEST_SHORTCODE, + static function () { + return ''; + } + ); + + $content = sprintf( + "This shouldn't stay straight, and this should become a smilie: :mrgreen:\n\n

[%s]

\n\n\n\n\"\"\n\nhttps://example.com/apply-block-content-filters", + self::TEST_SHORTCODE + ); + + $output = _wp_apply_block_content_filters( $content, 'test-context' ); + + $this->assertStringContainsString( + 'This shouldn’t stay straight', + $output, + 'wptexturize() should process the filtered content.' + ); + $this->assertStringContainsString( + 'class="wp-smiley"', + $output, + 'convert_smilies() should process smilies in the filtered content.' + ); + $this->assertStringContainsString( + '
Shortcode block output
', + $output, + 'do_shortcode() should run before do_blocks() so block markup returned by a shortcode is rendered.' + ); + $this->assertStringNotContainsString( + '

Shortcode block output

', + $output, + 'shortcode_unautop() should remove paragraph wrappers around standalone shortcodes.' + ); + $this->assertStringContainsString( + '
Direct block output
', + $output, + 'do_blocks() should render block markup in the filtered content.' + ); + $this->assertStringNotContainsString( + '', + 'test-context', + $seen_ids, + 'test-id' + ); + + $this->assertStringContainsString( + 'Seen ID checked', + $output, + 'The test block should render while the ID is marked as seen.' + ); + $this->assertSame( + array( 'test-id' => true ), + $seen_ids_during_render, + 'The ID should be marked as seen while do_blocks() renders nested blocks.' + ); + $this->assertSame( + array(), + $seen_ids, + 'The seen ID should be cleared after do_blocks() completes.' + ); + } + + /** + * Tests that seen IDs are cleared when block rendering throws an exception. + * + * @ticket 65586 + */ + public function test_clears_seen_id_when_block_rendering_throws() { + $seen_ids = array(); + + try { + _wp_apply_block_content_filters( + '', + 'test-context', + $seen_ids, + 'test-id' + ); + $this->fail( 'Expected block rendering to throw an exception.' ); + } catch ( Exception $exception ) { + $this->assertSame( + 'Block rendering failed.', + $exception->getMessage(), + 'The exception from the nested block render callback should be rethrown.' + ); + } + + $this->assertSame( + array(), + $seen_ids, + 'The seen ID should be cleared when do_blocks() throws.' + ); + } +} From 1f10a7c483e40018922ee263adb891088e56f3d7 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 15 Jul 2026 11:32:02 +0100 Subject: [PATCH 2/2] Tests: Clarify block content filter test expectations --- .../tests/blocks/wpApplyBlockContentFilters.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/phpunit/tests/blocks/wpApplyBlockContentFilters.php b/tests/phpunit/tests/blocks/wpApplyBlockContentFilters.php index c3ad1b7f06a77..56ee579dab8ff 100644 --- a/tests/phpunit/tests/blocks/wpApplyBlockContentFilters.php +++ b/tests/phpunit/tests/blocks/wpApplyBlockContentFilters.php @@ -126,16 +126,16 @@ static function () { ); $content = sprintf( - "This shouldn't stay straight, and this should become a smilie: :mrgreen:\n\n

[%s]

\n\n\n\n\"\"\n\nhttps://example.com/apply-block-content-filters", + "This shouldn't use a straight apostrophe, and this should become a smilie: :mrgreen:\n\n

[%s]

\n\n\n\n\"\"\n\nhttps://example.com/apply-block-content-filters", self::TEST_SHORTCODE ); $output = _wp_apply_block_content_filters( $content, 'test-context' ); $this->assertStringContainsString( - 'This shouldn’t stay straight', + 'This shouldn’t use a straight apostrophe', $output, - 'wptexturize() should process the filtered content.' + 'wptexturize() should convert straight apostrophes to curly apostrophe entities.' ); $this->assertStringContainsString( 'class="wp-smiley"', @@ -200,7 +200,7 @@ public function test_marks_and_clears_seen_id() { 'render_callback' => static function () use ( &$seen_ids, &$seen_ids_during_render ) { $seen_ids_during_render = $seen_ids; - return '
Seen ID checked
'; + return '
Nested block rendered while recursion guard was active
'; }, ) ); @@ -213,7 +213,7 @@ public function test_marks_and_clears_seen_id() { ); $this->assertStringContainsString( - 'Seen ID checked', + 'Nested block rendered while recursion guard was active', $output, 'The test block should render while the ID is marked as seen.' );