diff --git a/includes/blocks/simplified-summary/block.json b/includes/blocks/simplified-summary/block.json new file mode 100644 index 000000000..0dc3fc6d7 --- /dev/null +++ b/includes/blocks/simplified-summary/block.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "edac/simplified-summary", + "title": "Simplified Summary", + "description": "Displays this post's simplified summary from Accessibility Checker.", + "category": "accessibility-checker", + "icon": "universal-access-alt", + "keywords": [ "accessibility", "summary", "readability" ], + "textdomain": "accessibility-checker", + "usesContext": [ "postId" ], + "supports": { + "html": false, + "multiple": false, + "spacing": { + "margin": true + } + }, + "editorScript": "edac-simplified-summary-block", + "editorStyle": "edac-simplified-summary-block-editor" +} diff --git a/includes/classes/Blocks/SimplifiedSummaryBlock.php b/includes/classes/Blocks/SimplifiedSummaryBlock.php new file mode 100644 index 000000000..f35b34ec1 --- /dev/null +++ b/includes/classes/Blocks/SimplifiedSummaryBlock.php @@ -0,0 +1,182 @@ + self::CATEGORY, + 'title' => esc_html__( 'Accessibility Checker', 'accessibility-checker' ), + 'icon' => null, + ]; + + return $categories; + } + + /** + * Register the block and its editor assets. + * + * The build does not generate *.asset.php files, so the editor script is + * registered here with an explicit dependency list and block.json + * references the handle rather than a file. + * + * @since 1.xx.x + * + * @return void + */ + public function register() { + if ( \WP_Block_Type_Registry::get_instance()->is_registered( self::BLOCK_NAME ) ) { + return; + } + + wp_register_script( + self::SCRIPT_HANDLE, + plugin_dir_url( EDAC_PLUGIN_FILE ) . 'build/simplifiedSummaryBlock.bundle.js', + [ 'wp-blocks', 'wp-element', 'wp-i18n', 'wp-block-editor' ], + EDAC_VERSION, + true + ); + + wp_set_script_translations( + self::SCRIPT_HANDLE, + 'accessibility-checker', + plugin_dir_path( EDAC_PLUGIN_FILE ) . 'languages' + ); + + wp_localize_script( + self::SCRIPT_HANDLE, + 'edacSimplifiedSummaryBlock', + [ + /** This filter is documented in includes/classes/class-simplified-summary.php */ + 'heading' => apply_filters( + 'edac_filter_simplified_summary_heading', + esc_html__( 'Simplified Summary', 'accessibility-checker' ) + ), + ] + ); + + wp_register_style( + self::STYLE_HANDLE, + plugin_dir_url( EDAC_PLUGIN_FILE ) . 'build/css/simplifiedSummaryBlock.css', + [], + EDAC_VERSION + ); + + register_block_type( + EDAC_PLUGIN_DIR . 'includes/blocks/simplified-summary', + [ 'render_callback' => [ $this, 'render' ] ] + ); + } + + /** + * Render the block on the front end. + * + * Uses the postId block context when available (FSE templates, Query + * Loop) and falls back to the global post. Renders regardless of the + * edac_simplified_summary_prompt option because manual placement is a + * deliberate act, matching edac_get_simplified_summary(). + * + * @since 1.xx.x + * + * @param array $attributes The block attributes. + * @param string $content The block content. + * @param WP_Block|null $block The block instance. + * @return string + */ + public function render( $attributes, $content, $block = null ) { + $post_id = ( $block instanceof WP_Block && isset( $block->context['postId'] ) ) + ? (int) $block->context['postId'] + : (int) get_the_ID(); + + if ( ! $post_id ) { + return ''; + } + + $markup = ( new Simplified_Summary() )->simplified_summary_markup( $post_id ); + + if ( ! $markup ) { + return ''; + } + + // The wrapper carries the block supports output (margin classes/styles). + // get_block_wrapper_attributes() requires an active block render; guard + // against direct calls to this callback outside of one. + $wrapper_attributes = null !== \WP_Block_Supports::$block_to_render + ? get_block_wrapper_attributes() + : 'class="wp-block-edac-simplified-summary"'; + + return sprintf( '
%s
', $wrapper_attributes, $markup ); + } +} diff --git a/includes/classes/Shortcodes/SimplifiedSummaryShortcode.php b/includes/classes/Shortcodes/SimplifiedSummaryShortcode.php new file mode 100644 index 000000000..5a94525c1 --- /dev/null +++ b/includes/classes/Shortcodes/SimplifiedSummaryShortcode.php @@ -0,0 +1,75 @@ + 0 ], + $atts, + self::SHORTCODE + ); + + $explicit_post_id = absint( $atts['post_id'] ); + + if ( $explicit_post_id && ! is_post_publicly_viewable( $explicit_post_id ) ) { + return ''; + } + + $post_id = $explicit_post_id ? $explicit_post_id : (int) get_the_ID(); + + if ( ! $post_id ) { + return ''; + } + + return ( new Simplified_Summary() )->simplified_summary_markup( $post_id ); + } +} diff --git a/includes/classes/class-plugin.php b/includes/classes/class-plugin.php index ee40dc785..303dedeb9 100644 --- a/includes/classes/class-plugin.php +++ b/includes/classes/class-plugin.php @@ -11,7 +11,9 @@ use EDAC\Admin\Meta_Boxes; use EDAC\Admin\Orphaned_Issues_Cleanup; use EqualizeDigital\AccessibilityChecker\Admin\AdminPage\AccessibilityReportsPage; +use EqualizeDigital\AccessibilityChecker\Blocks\SimplifiedSummaryBlock; use EqualizeDigital\AccessibilityChecker\MyDot\Connector; +use EqualizeDigital\AccessibilityChecker\Shortcodes\SimplifiedSummaryShortcode; use EqualizeDigital\AccessibilityChecker\WPCLI\BootstrapCLI; use EqualizeDigital\AccessibilityChecker\Fixes\FixesManager; @@ -47,6 +49,13 @@ public function __construct() { $cleanup = new Orphaned_Issues_Cleanup(); $cleanup->init_hooks(); + // The block and shortcode must register in admin (for the editor) and on the front end. + $simplified_summary_block = new SimplifiedSummaryBlock(); + $simplified_summary_block->init_hooks(); + + $simplified_summary_shortcode = new SimplifiedSummaryShortcode(); + $simplified_summary_shortcode->init_hooks(); + $this->register_fixes_manager(); $this->register_sr_only_meta_hooks(); diff --git a/includes/classes/class-simplified-summary.php b/includes/classes/class-simplified-summary.php index ca3fc6e5b..93ddd1c60 100644 --- a/includes/classes/class-simplified-summary.php +++ b/includes/classes/class-simplified-summary.php @@ -40,6 +40,9 @@ public function output_simplified_summary( $content ) { if ( 'none' === $simplified_summary_prompt ) { return $content; } + if ( $this->is_manually_placed( get_the_ID() ) ) { + return $content; + } $simplified_summary = $this->simplified_summary_markup( get_the_ID() ); $simplified_summary_position = get_option( 'edac_simplified_summary_position', $default = false ); @@ -54,6 +57,58 @@ public function output_simplified_summary( $content ) { return $content; } + /** + * Check whether the simplified summary has been manually placed for a post. + * + * Detects the edac/simplified-summary block or [edac_simplified_summary] + * shortcode in the post content, and the block in the current block theme + * template. Blocks nested inside template parts or synced patterns cannot + * be detected by has_block(); the filter below is the escape hatch for + * those cases. + * + * @since 1.xx.x + * + * @param int|\WP_Post|null $post Post ID or post object. + * @return bool + */ + public function is_manually_placed( $post = null ): bool { + $manually_placed = false; + + $post = get_post( $post ); + if ( $post instanceof \WP_Post ) { + if ( + has_block( 'edac/simplified-summary', $post ) || + has_shortcode( (string) $post->post_content, 'edac_simplified_summary' ) + ) { + $manually_placed = true; + } + } + + // Set by WordPress when rendering a block theme template. + global $_wp_current_template_content; + if ( + ! $manually_placed && + ! empty( $_wp_current_template_content ) && + ( + has_block( 'edac/simplified-summary', $_wp_current_template_content ) || + has_shortcode( $_wp_current_template_content, 'edac_simplified_summary' ) + ) + ) { + $manually_placed = true; + } + + /** + * Filter whether the simplified summary is manually placed, which + * suppresses the automatic insertion on the_content. + * + * @since 1.xx.x + * + * @param bool $manually_placed Whether the summary is manually placed. + * @param \WP_Post|null $post The post being checked. + */ + return apply_filters( 'edac_filter_simplified_summary_is_manually_placed', $manually_placed, $post ); + } + /** * Simplified summary markup * diff --git a/readme.txt b/readme.txt index 8854adaec..8f148306b 100644 --- a/readme.txt +++ b/readme.txt @@ -168,6 +168,7 @@ Current settings in the free plugin include: * Control if you want scans to run on both pages and posts. * Control when the plugin prompts for a simplified summary. * Choose the position of the simplified summary above content, below content, or manually in a template. +* Place the simplified summary anywhere with the Simplified Summary block or the `[edac_simplified_summary]` shortcode (accepts an optional `post_id` attribute); manual placement automatically disables the automatic insertion for that post. * Add footer accessibility statement. * Choose positioning for the front-end Accessibility Checker. * Show or hide the Accessibility Checker metabox in the block editor. diff --git a/src/simplifiedSummaryBlock/edit.js b/src/simplifiedSummaryBlock/edit.js new file mode 100644 index 000000000..e4def03de --- /dev/null +++ b/src/simplifiedSummaryBlock/edit.js @@ -0,0 +1,37 @@ +import { useBlockProps } from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; + +/** + * Editor view for the simplified summary block. + * + * The summary is authored in the Accessibility Checker sidebar panel, not in + * the block, so the editor shows a static placeholder mirroring the front end + * markup shape. The heading is localized server-side with the + * edac_filter_simplified_summary_heading filter applied, so a custom heading + * (a pro setting) previews exactly as it renders on the front end. + * + * @return {Object} The block edit component. + */ +const Edit = () => { + const blockProps = useBlockProps( { + className: 'edac-simplified-summary', + } ); + + const heading = + window.edacSimplifiedSummaryBlock?.heading || + __( 'Simplified Summary', 'accessibility-checker' ); + + return ( +
+

{ heading }

+

+ { __( + 'The simplified summary for this post will display here. Write the summary in the Readability section of the Accessibility Checker sidebar or meta box.', + 'accessibility-checker' + ) } +

+
+ ); +}; + +export default Edit; diff --git a/src/simplifiedSummaryBlock/index.js b/src/simplifiedSummaryBlock/index.js new file mode 100644 index 000000000..07064e8eb --- /dev/null +++ b/src/simplifiedSummaryBlock/index.js @@ -0,0 +1,11 @@ +import { registerBlockType } from '@wordpress/blocks'; +import Edit from './edit'; + +/** + * The block is dynamic: metadata comes from block.json server-side and the + * front end output is produced by a PHP render callback, so save returns null. + */ +registerBlockType( 'edac/simplified-summary', { + edit: Edit, + save: () => null, +} ); diff --git a/src/simplifiedSummaryBlock/sass/simplified-summary-block.scss b/src/simplifiedSummaryBlock/sass/simplified-summary-block.scss new file mode 100644 index 000000000..c356b7361 --- /dev/null +++ b/src/simplifiedSummaryBlock/sass/simplified-summary-block.scss @@ -0,0 +1,9 @@ +// Editor-only styles for the simplified summary block placeholder. +.edac-simplified-summary { + .edac-simplified-summary-block__placeholder { + border: 1px dashed currentcolor; + border-radius: 2px; + opacity: 0.62; + padding: 0.75em 1em; + } +} diff --git a/tests/jest/simplifiedSummaryBlock/index.test.js b/tests/jest/simplifiedSummaryBlock/index.test.js new file mode 100644 index 000000000..65340285a --- /dev/null +++ b/tests/jest/simplifiedSummaryBlock/index.test.js @@ -0,0 +1,65 @@ +/** + * Tests for the simplified summary block registration and edit component. + * + * @wordpress/blocks and @wordpress/block-editor are webpack externals and not + * installed as packages, so they are mocked here. + */ +import { renderReact } from '../helpers/renderReact'; + +jest.mock( '@wordpress/blocks', () => ( { + registerBlockType: jest.fn(), +} ), { virtual: true } ); + +jest.mock( '@wordpress/block-editor', () => ( { + useBlockProps: jest.fn( ( props ) => props ), +} ), { virtual: true } ); + +import { registerBlockType } from '@wordpress/blocks'; +import Edit from '../../../src/simplifiedSummaryBlock/edit'; +import '../../../src/simplifiedSummaryBlock/index'; + +describe( 'simplified summary block registration', () => { + test( 'registers the edac/simplified-summary block', () => { + expect( registerBlockType ).toHaveBeenCalledTimes( 1 ); + expect( registerBlockType ).toHaveBeenCalledWith( + 'edac/simplified-summary', + expect.objectContaining( { + edit: Edit, + save: expect.any( Function ), + } ), + ); + } ); + + test( 'save returns null so the block is dynamic', () => { + const { save } = registerBlockType.mock.calls[ 0 ][ 1 ]; + expect( save() ).toBeNull(); + } ); +} ); + +describe( 'Edit', () => { + afterEach( () => { + delete window.edacSimplifiedSummaryBlock; + } ); + + test( 'renders the default heading and placeholder text', () => { + const { container, unmount } = renderReact( ); + expect( container.querySelector( 'h2' ).textContent ).toBe( 'Simplified Summary' ); + expect( + container.querySelector( '.edac-simplified-summary-block__placeholder' ).textContent, + ).toContain( 'will display here' ); + unmount(); + } ); + + test( 'renders the localized heading when provided', () => { + window.edacSimplifiedSummaryBlock = { heading: 'TL;DR' }; + const { container, unmount } = renderReact( ); + expect( container.querySelector( 'h2' ).textContent ).toBe( 'TL;DR' ); + unmount(); + } ); + + test( 'applies the frontend wrapper class via block props', () => { + const { container, unmount } = renderReact( ); + expect( container.querySelector( '.edac-simplified-summary' ) ).not.toBeNull(); + unmount(); + } ); +} ); diff --git a/tests/phpunit/includes/classes/Blocks/SimplifiedSummaryBlockTest.php b/tests/phpunit/includes/classes/Blocks/SimplifiedSummaryBlockTest.php new file mode 100644 index 000000000..8b871779f --- /dev/null +++ b/tests/phpunit/includes/classes/Blocks/SimplifiedSummaryBlockTest.php @@ -0,0 +1,175 @@ +block = new SimplifiedSummaryBlock(); + + // The registry persists across tests while the scripts registry resets, + // so unregister first to exercise a full registration every time. + if ( WP_Block_Type_Registry::get_instance()->is_registered( SimplifiedSummaryBlock::BLOCK_NAME ) ) { + unregister_block_type( SimplifiedSummaryBlock::BLOCK_NAME ); + } + $this->block->register(); + } + + /** + * Tests that the block and its editor script are registered. + * + * @return void + */ + public function test_register_registers_block_and_script() { + $this->assertTrue( WP_Block_Type_Registry::get_instance()->is_registered( SimplifiedSummaryBlock::BLOCK_NAME ) ); + $this->assertTrue( wp_script_is( SimplifiedSummaryBlock::SCRIPT_HANDLE, 'registered' ) ); + $this->assertTrue( wp_style_is( SimplifiedSummaryBlock::STYLE_HANDLE, 'registered' ) ); + } + + /** + * Tests that the block category is registered once and the block uses it. + * + * @return void + */ + public function test_register_block_category() { + $categories = $this->block->register_block_category( [] ); + $this->assertContains( SimplifiedSummaryBlock::CATEGORY, wp_list_pluck( $categories, 'slug' ) ); + + // Running the filter again must not duplicate the category. + $categories = $this->block->register_block_category( $categories ); + $this->assertCount( 1, $categories ); + + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( SimplifiedSummaryBlock::BLOCK_NAME ); + $this->assertSame( SimplifiedSummaryBlock::CATEGORY, $block_type->category ); + } + + /** + * Tests that render uses the postId block context. + * + * @return void + */ + public function test_render_uses_post_id_context() { + $post_id = self::factory()->post->create(); + update_post_meta( $post_id, '_edac_simplified_summary', 'Context summary.' ); + + $block = new WP_Block( + [ 'blockName' => SimplifiedSummaryBlock::BLOCK_NAME ], + [ 'postId' => $post_id ] + ); + + $output = $this->block->render( [], '', $block ); + $this->assertStringContainsString( 'Context summary.', $output ); + $this->assertStringContainsString( 'edac-simplified-summary', $output ); + } + + /** + * Tests that render falls back to the global post without context. + * + * @return void + */ + public function test_render_falls_back_to_global_post() { + $post_id = self::factory()->post->create(); + update_post_meta( $post_id, '_edac_simplified_summary', 'Global post summary.' ); + + global $post; + $post = get_post( $post_id ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Setting up the loop for the test. + setup_postdata( $post ); + + $block = new WP_Block( [ 'blockName' => SimplifiedSummaryBlock::BLOCK_NAME ] ); + + $output = $this->block->render( [], '', $block ); + $this->assertStringContainsString( 'Global post summary.', $output ); + } + + /** + * Tests that render returns an empty string when there is no summary. + * + * @return void + */ + public function test_render_returns_empty_string_without_summary() { + $post_id = self::factory()->post->create(); + + $block = new WP_Block( + [ 'blockName' => SimplifiedSummaryBlock::BLOCK_NAME ], + [ 'postId' => $post_id ] + ); + + $this->assertSame( '', $this->block->render( [], '', $block ) ); + } + + /** + * Tests that render returns an empty string when there is no post at all. + * + * @return void + */ + public function test_render_returns_empty_string_without_post() { + global $post; + $post = null; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Clearing the loop for the test. + + $block = new WP_Block( [ 'blockName' => SimplifiedSummaryBlock::BLOCK_NAME ] ); + + $this->assertSame( '', $this->block->render( [], '', $block ) ); + } + + /** + * Tests that the block renders end-to-end through do_blocks. + * + * @return void + */ + public function test_block_renders_through_do_blocks() { + $post_id = self::factory()->post->create(); + update_post_meta( $post_id, '_edac_simplified_summary', 'Do blocks summary.' ); + + global $post; + $post = get_post( $post_id ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Setting up the loop for the test. + setup_postdata( $post ); + + $output = do_blocks( '' ); + $this->assertStringContainsString( 'Do blocks summary.', $output ); + $this->assertStringContainsString( 'wp-block-edac-simplified-summary', $output ); + } + + /** + * Tests that the block renders even when the prompt option is set to none. + * + * Manual placement is a deliberate act and is not gated by the + * edac_simplified_summary_prompt option. + * + * @return void + */ + public function test_render_ignores_prompt_none_option() { + update_option( 'edac_simplified_summary_prompt', 'none' ); + + $post_id = self::factory()->post->create(); + update_post_meta( $post_id, '_edac_simplified_summary', 'Prompt none summary.' ); + + $block = new WP_Block( + [ 'blockName' => SimplifiedSummaryBlock::BLOCK_NAME ], + [ 'postId' => $post_id ] + ); + + $output = $this->block->render( [], '', $block ); + $this->assertStringContainsString( 'Prompt none summary.', $output ); + } +} diff --git a/tests/phpunit/includes/classes/Shortcodes/SimplifiedSummaryShortcodeTest.php b/tests/phpunit/includes/classes/Shortcodes/SimplifiedSummaryShortcodeTest.php new file mode 100644 index 000000000..5563d60aa --- /dev/null +++ b/tests/phpunit/includes/classes/Shortcodes/SimplifiedSummaryShortcodeTest.php @@ -0,0 +1,99 @@ +init_hooks(); + } + } + + /** + * Tests that the shortcode renders the summary for the current post. + * + * @return void + */ + public function test_shortcode_renders_summary_for_current_post() { + $post_id = self::factory()->post->create(); + update_post_meta( $post_id, '_edac_simplified_summary', 'Shortcode summary.' ); + + global $post; + $post = get_post( $post_id ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Setting up the loop for the test. + setup_postdata( $post ); + + $output = do_shortcode( '[edac_simplified_summary]' ); + $this->assertStringContainsString( 'Shortcode summary.', $output ); + $this->assertStringContainsString( 'edac-simplified-summary', $output ); + } + + /** + * Tests that the shortcode accepts an explicit post_id attribute. + * + * @return void + */ + public function test_shortcode_accepts_post_id_attribute() { + $post_id = self::factory()->post->create(); + update_post_meta( $post_id, '_edac_simplified_summary', 'Attribute summary.' ); + + $output = do_shortcode( '[edac_simplified_summary post_id="' . $post_id . '"]' ); + $this->assertStringContainsString( 'Attribute summary.', $output ); + } + + /** + * Tests that the shortcode returns an empty string when the post has no summary. + * + * @return void + */ + public function test_shortcode_returns_empty_string_without_summary() { + $post_id = self::factory()->post->create(); + + $output = do_shortcode( '[edac_simplified_summary post_id="' . $post_id . '"]' ); + $this->assertSame( '', $output ); + } + + /** + * Tests that the shortcode does not expose summaries of non-public posts. + * + * @return void + */ + public function test_shortcode_does_not_render_non_public_posts() { + $draft_id = self::factory()->post->create( [ 'post_status' => 'draft' ] ); + update_post_meta( $draft_id, '_edac_simplified_summary', 'Draft summary.' ); + + $private_id = self::factory()->post->create( [ 'post_status' => 'private' ] ); + update_post_meta( $private_id, '_edac_simplified_summary', 'Private summary.' ); + + $this->assertSame( '', do_shortcode( '[edac_simplified_summary post_id="' . $draft_id . '"]' ) ); + $this->assertSame( '', do_shortcode( '[edac_simplified_summary post_id="' . $private_id . '"]' ) ); + } + + /** + * Tests that the shortcode returns an empty string outside the loop with no post_id. + * + * @return void + */ + public function test_shortcode_returns_empty_string_without_post() { + global $post; + $post = null; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Clearing the loop for the test. + + $output = do_shortcode( '[edac_simplified_summary]' ); + $this->assertSame( '', $output ); + } +} diff --git a/tests/phpunit/includes/classes/SimplifiedSummaryTest.php b/tests/phpunit/includes/classes/SimplifiedSummaryTest.php index 5044cf4e2..f52f137de 100644 --- a/tests/phpunit/includes/classes/SimplifiedSummaryTest.php +++ b/tests/phpunit/includes/classes/SimplifiedSummaryTest.php @@ -34,6 +34,19 @@ public function setUp(): void { $this->simplified_summary = new Simplified_Summary(); } + /** + * Clean up the test fixture. + * + * The core test framework does not reset the block template global. + * + * @return void + */ + public function tearDown(): void { + global $_wp_current_template_content; + $_wp_current_template_content = null; + parent::tearDown(); + } + /** * Tests output of simplified_summary_markup with a summary. * @@ -67,4 +80,108 @@ public function test_simplified_summary_markup_without_summary() { $output = $this->simplified_summary->simplified_summary_markup( $post_id ); $this->assertEmpty( $output ); } + + /** + * Creates a post with a summary and sets it up as the current global post. + * + * @param string $content The post content. + * @return int The post ID. + */ + private function create_post_in_loop( $content = 'Post content.' ) { + $post_id = self::factory()->post->create( [ 'post_content' => $content ] ); + update_post_meta( $post_id, '_edac_simplified_summary', 'This is a simplified summary.' ); + update_option( 'edac_simplified_summary_prompt', 'always' ); + update_option( 'edac_simplified_summary_position', 'after' ); + + global $post; + $post = get_post( $post_id ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Setting up the loop for the test. + setup_postdata( $post ); + + return $post_id; + } + + /** + * Tests that the summary is auto-inserted when not manually placed. + * + * @return void + */ + public function test_output_simplified_summary_auto_inserts_when_not_manually_placed() { + $this->create_post_in_loop(); + + $output = $this->simplified_summary->output_simplified_summary( 'Post content.' ); + $this->assertStringContainsString( 'edac-simplified-summary', $output ); + } + + /** + * Tests that auto-insertion is suppressed when the block is in the post content. + * + * @return void + */ + public function test_output_simplified_summary_suppressed_when_block_in_content() { + $this->create_post_in_loop( '

Post content.

' ); + + $output = $this->simplified_summary->output_simplified_summary( 'Post content.' ); + $this->assertStringNotContainsString( 'edac-simplified-summary', $output ); + } + + /** + * Tests that auto-insertion is suppressed when the shortcode is in the post content. + * + * @return void + */ + public function test_output_simplified_summary_suppressed_when_shortcode_in_content() { + $this->create_post_in_loop( 'Post content. [edac_simplified_summary]' ); + + $output = $this->simplified_summary->output_simplified_summary( 'Post content.' ); + $this->assertStringNotContainsString( 'edac-simplified-summary', $output ); + } + + /** + * Tests that auto-insertion is suppressed when the block is in the current block theme template. + * + * @return void + */ + public function test_output_simplified_summary_suppressed_when_block_in_template() { + $this->create_post_in_loop(); + + global $_wp_current_template_content; + $_wp_current_template_content = ''; + + $output = $this->simplified_summary->output_simplified_summary( 'Post content.' ); + + $this->assertStringNotContainsString( 'edac-simplified-summary', $output ); + } + + /** + * Tests that auto-insertion is suppressed when the shortcode is in the current block theme template. + * + * Covers a core Shortcode block containing [edac_simplified_summary] in an FSE template. + * + * @return void + */ + public function test_output_simplified_summary_suppressed_when_shortcode_in_template() { + $this->create_post_in_loop(); + + global $_wp_current_template_content; + $_wp_current_template_content = '[edac_simplified_summary]'; + + $output = $this->simplified_summary->output_simplified_summary( 'Post content.' ); + + $this->assertStringNotContainsString( 'edac-simplified-summary', $output ); + } + + /** + * Tests that the manually placed filter can suppress auto-insertion. + * + * @return void + */ + public function test_output_simplified_summary_suppressed_by_filter() { + $this->create_post_in_loop(); + + add_filter( 'edac_filter_simplified_summary_is_manually_placed', '__return_true' ); + $output = $this->simplified_summary->output_simplified_summary( 'Post content.' ); + remove_filter( 'edac_filter_simplified_summary_is_manually_placed', '__return_true' ); + + $this->assertStringNotContainsString( 'edac-simplified-summary', $output ); + } } diff --git a/webpack.config.js b/webpack.config.js index 82902f4cb..c294ecc88 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -43,6 +43,10 @@ module.exports = { './src/srOnlyFormat/index.js', './src/srOnlyFormat/sass/sr-only-format.scss', ], + simplifiedSummaryBlock: [ + './src/simplifiedSummaryBlock/index.js', + './src/simplifiedSummaryBlock/sass/simplified-summary-block.scss', + ], sharedComponents: { import: './src/sharedComponents/index.js', library: { @@ -126,6 +130,7 @@ module.exports = { externals: { // Exclude WordPress core scripts and styles from the build. '@wordpress/i18n': [ 'wp', 'i18n' ], + '@wordpress/blocks': [ 'wp', 'blocks' ], '@wordpress/plugins': [ 'wp', 'plugins' ], '@wordpress/editor': [ 'wp', 'editor' ], '@wordpress/edit-post': [ 'wp', 'editPost' ],