Tests: Cover Block Hooks integration with a custom block theme

Adds a simplified version of Twenty Twenty-Three theme that helps testing Block Hooks integration. The theme contains:

- The required index.html template.
- The optional single.html template used with tests.
- 3 template parts where two of them reference patterns.
- 3 patterns referenced in the templates and the template parts.

New tests automatically register 4 custom blocks with the test theme where each of them hooks into another block using all four target relative positions: `before`, `after`, `firstChild`, `lastChild`.

The tests verify that the block gets hooked into the correct positions when targeting:

- template
- template part
- pattern

Props ockham, costdev.
See #59313, #59383.
Follow-up [56610].


git-svn-id: https://develop.svn.wordpress.org/trunk@56759 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Greg Ziółkowski 2023-10-03 08:27:51 +00:00
parent a1852bd49b
commit d7c3092054
21 changed files with 519 additions and 122 deletions

View File

@ -0,0 +1,7 @@
{
"name": "tests/hooked-after",
"blockHooks": {
"core/post-content": "after"
},
"render": "file:render.php"
}

View File

@ -0,0 +1 @@
<p>Block hooked after.<p>

View File

@ -0,0 +1,7 @@
{
"name": "tests/hooked-before",
"blockHooks": {
"core/navigation": "before"
},
"render": "file:render.php"
}

View File

@ -0,0 +1 @@
<p>Block hooked before.<p>

View File

@ -0,0 +1,7 @@
{
"name": "tests/hooked-first-child",
"blockHooks": {
"core/comments": "firstChild"
},
"render": "file:render.php"
}

View File

@ -0,0 +1 @@
<p>Block hooked as the first child.<p>

View File

@ -0,0 +1,7 @@
{
"name": "tests/hooked-last-child",
"blockHooks": {
"core/comment-template": "lastChild"
},
"render": "file:render.php"
}

View File

@ -0,0 +1 @@
<p>Block hooked as the last child.<p>

View File

@ -0,0 +1 @@
<!-- wp:pattern {"slug":"block-theme-with-hooked-blocks/hidden-comments"} /-->

View File

@ -0,0 +1 @@
<!-- wp:pattern {"slug":"block-theme-with-hooked-blocks/footer-default"} /-->

View File

@ -0,0 +1,10 @@
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:group {"align":"wide","layout":{"type":"flex","justifyContent":"space-between"}} -->
<div class="wp-block-group alignwide">
<!-- wp:site-title {"level":0} /-->
<!-- wp:navigation {"layout":{"type":"flex","setCascadingProperties":true,"justifyContent":"right"}} /-->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->

View File

@ -0,0 +1,28 @@
<?php
/**
* Title: Default Footer
* Slug: block-theme-with-hooked-blocks/footer-default
* Categories: footer
* Block Types: core/template-part/footer
*/
?>
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:group {"align":"wide","layout":{"type":"flex","justifyContent":"space-between"}} -->
<div class="wp-block-group alignwide">
<!-- wp:site-title {"level":0} /-->
<!-- wp:paragraph {"align":"right"} -->
<p class="has-text-align-right">
<?php
printf(
/* Translators: WordPress link. */
esc_html__( 'Proudly powered by %s', 'block-theme-with-hooked-blocks' ),
'<a href="' . esc_url( __( 'https://wordpress.org', 'block-theme-with-hooked-blocks' ) ) . '" rel="nofollow">WordPress</a>'
)
?>
</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->

View File

@ -0,0 +1,57 @@
<?php
/**
* Title: Hidden Comments
* Slug: block-theme-with-hooked-blocks/hidden-comments
* Inserter: no
*/
?>
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group" >
<!-- wp:comments -->
<div class="wp-block-comments">
<!-- wp:heading {"level":2} -->
<h2><?php echo esc_html_x( 'Comments', 'Title of comments section', 'block-theme-with-hooked-blocks' ); ?></h2>
<!-- /wp:heading -->
<!-- wp:comments-title {"level":3} /-->
<!-- wp:comment-template -->
<!-- wp:columns -->
<div class="wp-block-columns">
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:avatar /-->
</div>
<!-- /wp:column -->
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:comment-author-name /-->
<!-- wp:group -->
<div class="wp-block-group">
<!-- wp:comment-date /-->
<!-- wp:comment-edit-link /-->
</div>
<!-- /wp:group -->
<!-- wp:comment-content /-->
<!-- wp:comment-reply-link /-->
</div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->
<!-- /wp:comment-template -->
<!-- wp:comments-pagination {"paginationArrow":"arrow","layout":{"type":"flex","justifyContent":"space-between"}} -->
<!-- wp:comments-pagination-previous /-->
<!-- wp:comments-pagination-numbers /-->
<!-- wp:comments-pagination-next /-->
<!-- /wp:comments-pagination -->
<!-- wp:post-comments-form /-->
</div>
<!-- /wp:comments -->
</div>
<!-- /wp:group -->

View File

@ -0,0 +1,76 @@
<?php
/**
* Title: Post Meta
* Slug: block-theme-with-hooked-blocks/post-meta
* Categories: query
* Keywords: post meta
* Block Types: core/template-part/post-meta
*/
?>
<!-- wp:spacer {"height":"0"} -->
<div style="height:0" aria-hidden="true" class="wp-block-spacer"></div>
<!-- /wp:spacer -->
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:separator {"opacity":"css","align":"wide","className":"is-style-wide"} -->
<hr class="wp-block-separator alignwide has-css-opacity is-style-wide"/>
<!-- /wp:separator -->
<!-- wp:columns -->
<div class="wp-block-columns">
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:group {"layout":{"type":"flex"}} -->
<div class="wp-block-group">
<!-- wp:paragraph -->
<p>
<?php echo esc_html_x( 'Posted', 'Verb to explain the publication status of a post', 'block-theme-with-hooked-blocks' ); ?>
</p>
<!-- /wp:paragraph -->
<!-- wp:post-date /-->
<!-- wp:paragraph -->
<p>
<?php echo esc_html_x( 'in', 'Preposition to show the relationship between the post and its categories', 'block-theme-with-hooked-blocks' ); ?>
</p>
<!-- /wp:paragraph -->
<!-- wp:post-terms {"term":"category"} /-->
</div>
<!-- /wp:group -->
<!-- wp:group {"layout":{"type":"flex"}} -->
<div class="wp-block-group">
<!-- wp:paragraph -->
<p>
<?php echo esc_html_x( 'by', 'Preposition to show the relationship between the post and its author', 'block-theme-with-hooked-blocks' ); ?>
</p>
<!-- /wp:paragraph -->
<!-- wp:post-author {"showAvatar":false} /-->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:column -->
<!-- wp:column -->
<div class="wp-block-column">
<!-- wp:group {"layout":{"type":"flex","orientation":"vertical"}} -->
<div class="wp-block-group">
<!-- wp:paragraph -->
<p>
<?php echo esc_html_x( 'Tags:', 'Label for a list of post tags', 'block-theme-with-hooked-blocks' ); ?>
</p>
<!-- /wp:paragraph -->
<!-- wp:post-terms {"term":"post_tag"} /-->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->
</div>
<!-- /wp:group -->

View File

@ -0,0 +1,7 @@
/*
Theme Name: Block Theme with Hooked Blocks
Theme URI: https://wordpress.org/
Description: For testing purposes only.
Version: 1.0.0
Text Domain: block-theme-with-hooked-blocks
*/

View File

@ -0,0 +1,23 @@
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
<!-- wp:query {"query":{"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true,"taxQuery":null,"parents":[]},"displayLayout":{"type":"flex","columns":3},"align":"wide","layout":{"type":"default"}} -->
<div class="wp-block-query alignwide">
<!-- wp:post-template {"align":"wide"} -->
<!-- wp:post-featured-image {"isLink":true,"width":"100%","height":"clamp(15vw, 30vh, 400px)","align":"wide"} /-->
<!-- wp:post-title {"isLink":true,"align":"wide"} /-->
<!-- wp:post-excerpt /-->
<!-- wp:post-date {"isLink":true} /-->
<!-- /wp:post-template -->
<!-- wp:query-pagination {"paginationArrow":"arrow","align":"wide","layout":{"type":"flex","justifyContent":"space-between"}} -->
<!-- wp:query-pagination-previous /-->
<!-- wp:query-pagination-next /-->
<!-- /wp:query-pagination -->
</div>
<!-- /wp:query -->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->

View File

@ -0,0 +1,18 @@
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:group {"tagName":"main"} -->
<main class="wp-block-group">
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:post-featured-image /-->
<!-- wp:post-title /-->
</div>
<!-- /wp:group -->
<!-- wp:post-content {"layout":{"type":"constrained"}} /-->
<!-- wp:pattern {"slug":"block-theme-with-hooked-blocks/post-meta"} /-->
<!-- wp:template-part {"slug":"comments","tagName":"section"} /-->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->

View File

@ -0,0 +1,21 @@
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 2,
"templateParts": [
{
"area": "header",
"name": "header",
"title": "Header"
},
{
"area": "footer",
"name": "footer",
"title": "Footer"
},
{
"area": "uncategorized",
"name": "comments",
"title": "Comments"
}
]
}

View File

@ -1,122 +0,0 @@
<?php
/**
* Tests for block hooks feature functions.
*
* @package WordPress
* @subpackage Blocks
*
* @since 6.4.0
*
* @group blocks
*/
class Tests_Blocks_BlockHooks extends WP_UnitTestCase {
/**
* Tear down after each test.
*
* @since 6.4.0
*/
public function tear_down() {
$registry = WP_Block_Type_Registry::get_instance();
foreach ( array( 'tests/my-block', 'tests/my-container-block' ) as $block_name ) {
if ( $registry->is_registered( $block_name ) ) {
$registry->unregister( $block_name );
}
}
parent::tear_down();
}
/**
* @ticket 59383
*
* @covers ::get_hooked_blocks
*/
public function test_get_hooked_blocks_no_match_found() {
$result = get_hooked_blocks( 'tests/no-hooked-blocks' );
$this->assertSame( array(), $result );
}
/**
* @ticket 59383
*
* @covers ::get_hooked_blocks
*/
public function test_get_hooked_blocks_matches_found() {
register_block_type(
'tests/injected-one',
array(
'block_hooks' => array(
'tests/hooked-at-before' => 'before',
'tests/hooked-at-after' => 'after',
'tests/hooked-at-before-and-after' => 'before',
),
)
);
register_block_type(
'tests/injected-two',
array(
'block_hooks' => array(
'tests/hooked-at-before' => 'before',
'tests/hooked-at-after' => 'after',
'tests/hooked-at-before-and-after' => 'after',
'tests/hooked-at-first-child' => 'first_child',
'tests/hooked-at-last-child' => 'last_child',
),
)
);
$this->assertSame(
array(
'before' => array(
'tests/injected-one',
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-before' ),
'block hooked at the before position'
);
$this->assertSame(
array(
'after' => array(
'tests/injected-one',
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-after' ),
'block hooked at the after position'
);
$this->assertSame(
array(
'first_child' => array(
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-first-child' ),
'block hooked at the first child position'
);
$this->assertSame(
array(
'last_child' => array(
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-last-child' ),
'block hooked at the last child position'
);
$this->assertSame(
array(
'before' => array(
'tests/injected-one',
),
'after' => array(
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-before-and-after' ),
'block hooked before one block and after another'
);
}
}

View File

@ -0,0 +1,244 @@
<?php
/**
* Tests for the features using get_hooked_blocks function.
*
* @package WordPress
* @subpackage Blocks
*
* @since 6.4.0
*
* @group blocks
* @group block-hooks
*/
class Tests_Blocks_GetHookedBlocks extends WP_UnitTestCase {
const TEST_THEME_NAME = 'block-theme-with-hooked-blocks';
/**
* Tear down after each test.
*
* @since 6.4.0
*/
public function tear_down() {
// Removes test block types registered by test cases.
$block_types = WP_Block_Type_Registry::get_instance()->get_all_registered();
foreach ( $block_types as $block_type ) {
$block_name = $block_type->name;
if ( str_starts_with( $block_name, 'tests/' ) ) {
unregister_block_type( $block_name );
}
}
// Removes test block patterns registered with the test theme.
$patterns = WP_Block_Patterns_Registry::get_instance()->get_all_registered();
foreach ( $patterns as $pattern ) {
if ( empty( $pattern['slug'] ) ) {
continue;
}
$pattern_name = $pattern['slug'];
if ( str_starts_with( $pattern_name, self::TEST_THEME_NAME ) ) {
unregister_block_pattern( $pattern_name );
}
}
parent::tear_down();
}
private function switch_to_block_theme_hooked_blocks() {
switch_theme( self::TEST_THEME_NAME );
_register_theme_block_patterns();
$theme_blocks_dir = wp_normalize_path( realpath( get_theme_file_path( 'blocks' ) ) );
register_block_type( $theme_blocks_dir . '/hooked-before' );
register_block_type( $theme_blocks_dir . '/hooked-after' );
register_block_type( $theme_blocks_dir . '/hooked-first-child' );
register_block_type( $theme_blocks_dir . '/hooked-last-child' );
}
/**
* @ticket 59383
*
* @covers ::get_hooked_blocks
*/
public function test_get_hooked_blocks_no_match_found() {
$result = get_hooked_blocks( 'tests/no-hooked-blocks' );
$this->assertSame( array(), $result );
}
/**
* @ticket 59383
*
* @covers ::get_hooked_blocks
*/
public function test_get_hooked_blocks_matches_found() {
register_block_type(
'tests/injected-one',
array(
'block_hooks' => array(
'tests/hooked-at-before' => 'before',
'tests/hooked-at-after' => 'after',
'tests/hooked-at-before-and-after' => 'before',
),
)
);
register_block_type(
'tests/injected-two',
array(
'block_hooks' => array(
'tests/hooked-at-before' => 'before',
'tests/hooked-at-after' => 'after',
'tests/hooked-at-before-and-after' => 'after',
'tests/hooked-at-first-child' => 'first_child',
'tests/hooked-at-last-child' => 'last_child',
),
)
);
$this->assertSame(
array(
'before' => array(
'tests/injected-one',
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-before' ),
'block hooked at the before position'
);
$this->assertSame(
array(
'after' => array(
'tests/injected-one',
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-after' ),
'block hooked at the after position'
);
$this->assertSame(
array(
'first_child' => array(
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-first-child' ),
'block hooked at the first child position'
);
$this->assertSame(
array(
'last_child' => array(
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-last-child' ),
'block hooked at the last child position'
);
$this->assertSame(
array(
'before' => array(
'tests/injected-one',
),
'after' => array(
'tests/injected-two',
),
),
get_hooked_blocks( 'tests/hooked-at-before-and-after' ),
'block hooked before one block and after another'
);
}
/**
* @ticket 59313
*
* @covers ::get_hooked_blocks
* @covers ::get_block_file_template
*/
public function test_loading_template_with_hooked_blocks() {
$this->switch_to_block_theme_hooked_blocks();
$template = get_block_file_template( get_stylesheet() . '//single' );
$this->assertStringNotContainsString(
'<!-- wp:tests/hooked-before /-->',
$template->content
);
$this->assertStringContainsString(
'<!-- wp:post-content {"layout":{"type":"constrained"}} /-->'
. '<!-- wp:tests/hooked-after /-->',
$template->content
);
$this->assertStringNotContainsString(
'<!-- wp:tests/hooked-first-child /-->',
$template->content
);
$this->assertStringNotContainsString(
'<!-- wp:tests/hooked-last-child /-->',
$template->content
);
}
/**
* @ticket 59313
*
* @covers ::get_hooked_blocks
* @covers ::get_block_file_template
*/
public function test_loading_template_part_with_hooked_blocks() {
$this->switch_to_block_theme_hooked_blocks();
$template = get_block_file_template( get_stylesheet() . '//header', 'wp_template_part' );
$this->assertStringContainsString(
'<!-- wp:tests/hooked-before /-->'
. '<!-- wp:navigation {"layout":{"type":"flex","setCascadingProperties":true,"justifyContent":"right"}} /-->',
$template->content
);
$this->assertStringNotContainsString(
'<!-- wp:tests/hooked-after /-->',
$template->content
);
$this->assertStringNotContainsString(
'<!-- wp:tests/hooked-first-child /-->',
$template->content
);
$this->assertStringNotContainsString(
'<!-- wp:tests/hooked-last-child /-->',
$template->content
);
}
/**
* @ticket 59313
*
* @covers ::get_hooked_blocks
* @covers WP_Block_Patterns_Registry::get_registered
*/
public function test_loading_pattern_with_hooked_blocks() {
$this->switch_to_block_theme_hooked_blocks();
$pattern = WP_Block_Patterns_Registry::get_instance()->get_registered(
get_stylesheet() . '/hidden-comments'
);
$this->assertStringNotContainsString(
'<!-- wp:tests/hooked-before /-->',
$pattern['content']
);
$this->assertStringNotContainsString(
'<!-- wp:tests/hooked-after /-->',
$pattern['content']
);
$this->assertStringContainsString(
'<!-- wp:comments -->'
. '<div class="wp-block-comments">'
. '<!-- wp:tests/hooked-first-child /-->',
str_replace( array( "\n", "\t" ), '', $pattern['content'] )
);
$this->assertStringContainsString(
'<!-- wp:tests/hooked-last-child /-->'
. '<!-- /wp:comment-template -->',
str_replace( array( "\n", "\t" ), '', $pattern['content'] )
);
}
}

View File

@ -187,6 +187,7 @@ class Tests_Theme_ThemeDir extends WP_UnitTestCase {
'Block Theme Deprecated Path',
'Block Theme Post Content Default',
'Block Theme with defined Typography Fonts',
'Block Theme with Hooked Blocks',
'Empty `fontFace` in theme.json - no webfonts defined',
'A theme with the Update URI header',
);