 ); ?>/assets/images/ipsum-portrait-editorial.webp?ver=<?php echo esc_attr( wp_get_theme( get_template() )->get( 'Version' ) ); ?>)
 ); ?>)
diff --git a/src/wp-content/themes/ipsum/patterns/archive-full.php b/src/wp-content/themes/ipsum/patterns/archive-full.php index 64c9d6149576f..ea632d61157ff 100644 --- a/src/wp-content/themes/ipsum/patterns/archive-full.php +++ b/src/wp-content/themes/ipsum/patterns/archive-full.php @@ -5,7 +5,7 @@ * Categories: posts * Block Types: core/query * Viewport width: 1280 - * Description: The whole post in the stream — featured image, title, meta, full content, and the conversation link. The home feed, wherever you want it. + * Description: A listing of whole posts, like the home feed. Each post shows its featured image, title, meta, full content, and the conversation link. * * @package Ipsum * @since Ipsum 1.0 @@ -25,7 +25,7 @@
@@ -36,18 +36,18 @@ -
- + - +
diff --git a/src/wp-content/themes/ipsum/patterns/archive-minimal.php b/src/wp-content/themes/ipsum/patterns/archive-minimal.php index de136847b6b7f..4a0f40575f2b8 100644 --- a/src/wp-content/themes/ipsum/patterns/archive-minimal.php +++ b/src/wp-content/themes/ipsum/patterns/archive-minimal.php @@ -5,14 +5,14 @@ * Categories: posts * Block Types: core/query * Viewport width: 1280 - * Description: Big post titles and a whisper of meta — nothing else. + * Description: Big post titles and a whisper of meta, nothing else. * * @package Ipsum * @since Ipsum 1.0 */ ?> - +
- +
diff --git a/src/wp-content/themes/ipsum/patterns/archive-standard.php b/src/wp-content/themes/ipsum/patterns/archive-standard.php index 33eccc8d6ae1b..0a94a2ca926b4 100644 --- a/src/wp-content/themes/ipsum/patterns/archive-standard.php +++ b/src/wp-content/themes/ipsum/patterns/archive-standard.php @@ -5,15 +5,15 @@ * Categories: posts * Block Types: core/query * Viewport width: 1280 - * Description: Featured image, title, meta, and an excerpt with a Read more link — the classic listing. + * Description: The classic listing. Each post shows its featured image, title, meta, and an excerpt with a Read more link. * * @package Ipsum * @since Ipsum 1.0 */ ?> - -
diff --git a/src/wp-content/themes/ipsum/patterns/contact-say-hi.php b/src/wp-content/themes/ipsum/patterns/contact-say-hi.php index c17c43112f695..c51c9c4d2b7da 100644 --- a/src/wp-content/themes/ipsum/patterns/contact-say-hi.php +++ b/src/wp-content/themes/ipsum/patterns/contact-say-hi.php @@ -4,7 +4,7 @@ * Slug: ipsum/contact-say-hi * Categories: contact * Viewport width: 1280 - * Description: A centered contact invitation — a display heading with the reach-out link over a row of social icons. + * Description: A centered contact invitation. A display heading with the reach-out link sits over a row of social icons. * * @package Ipsum * @since Ipsum 1.0 @@ -17,7 +17,7 @@
Feel free to reach out.', 'ipsum' ) ); ?>
- + diff --git a/src/wp-content/themes/ipsum/patterns/cta-membership.php b/src/wp-content/themes/ipsum/patterns/cta-membership.php index ff099e13128f6..89b0ea937a1c0 100644 --- a/src/wp-content/themes/ipsum/patterns/cta-membership.php +++ b/src/wp-content/themes/ipsum/patterns/cta-membership.php @@ -1,20 +1,21 @@ - -diff --git a/src/wp-content/themes/ipsum/patterns/format-audio.php b/src/wp-content/themes/ipsum/patterns/format-audio.php index 096230582434b..e31e5963c0594 100644 --- a/src/wp-content/themes/ipsum/patterns/format-audio.php +++ b/src/wp-content/themes/ipsum/patterns/format-audio.php @@ -2,9 +2,10 @@ /** * Title: Format Audio * Slug: ipsum/format-audio - * Categories: posts + * Categories: ipsum_post-format + * Keywords: audio, podcast, episode, music, player * Viewport width: 1280 - * Description: An audio-format post body — cover art, title and a one-line description over the player. + * Description: An audio-format post body. It has cover art, a title and a one-line description over the player. * * @package Ipsum * @since Ipsum 1.0 @@ -12,9 +13,9 @@ ?> -
- +
@@ -62,11 +62,11 @@ - +
@@ -44,18 +44,18 @@ -
- + - +
@@ -41,18 +42,18 @@ -
- + - +
diff --git a/src/wp-content/themes/ipsum/patterns/hidden-sidebar.php b/src/wp-content/themes/ipsum/patterns/hidden-sidebar.php index 26bbaa83f545f..9ecbf4bf18059 100644 --- a/src/wp-content/themes/ipsum/patterns/hidden-sidebar.php +++ b/src/wp-content/themes/ipsum/patterns/hidden-sidebar.php @@ -3,14 +3,15 @@ * Title: Sidebar * Slug: ipsum/hidden-sidebar * Inserter: no + * Description: The Sidebar template part. It has the categories list and the five latest posts, each a title and how long ago it was published. The sidebar templates place it in a column beside the main content. * * @package Ipsum * @since Ipsum 1.0 */ ?> - - +
@@ -44,8 +44,8 @@
@@ -41,8 +42,8 @@
@@ -48,18 +48,18 @@ -
- + - +
essays.', 'ipsum' ) ); ?>
A pattern from the child theme.
+ diff --git a/tests/phpunit/data/themedir1/block-theme-with-hooked-blocks-child/style.css b/tests/phpunit/data/themedir1/block-theme-with-hooked-blocks-child/style.css new file mode 100644 index 0000000000000..ad341a112dc41 --- /dev/null +++ b/tests/phpunit/data/themedir1/block-theme-with-hooked-blocks-child/style.css @@ -0,0 +1,8 @@ +/* +Theme Name: Block Theme with Hooked Blocks Child Theme +Theme URI: https://wordpress.org/ +Description: For testing purposes only. +Template: block-theme-with-hooked-blocks +Version: 1.0.0 +Text Domain: block-theme-with-hooked-blocks-child +*/ diff --git a/tests/phpunit/tests/theme/ipsumDesignGuide.php b/tests/phpunit/tests/theme/ipsumDesignGuide.php new file mode 100644 index 0000000000000..dd43ff57e75ef --- /dev/null +++ b/tests/phpunit/tests/theme/ipsumDesignGuide.php @@ -0,0 +1,176 @@ +original_stylesheet = get_stylesheet(); + + /* + * Reading a pattern's content removes its `filePath` from the registry for the rest of + * the process, and the design guide used to depend on it. Give each test a registry of + * its own, so earlier tests can't change what it starts with. Replace it before the skip + * below, which still runs `tear_down()`. + */ + $this->original_registry = WP_Block_Patterns_Registry::get_instance(); + $this->registry_instance_property = new ReflectionProperty( 'WP_Block_Patterns_Registry', 'instance' ); + if ( PHP_VERSION_ID < 80100 ) { + $this->registry_instance_property->setAccessible( true ); + } + $this->registry_instance_property->setValue( null, new WP_Block_Patterns_Registry() ); + + // Ipsum isn't the active theme in the test suite, so its functions.php isn't loaded. + $abilities = WP_CONTENT_DIR . '/themes/ipsum/inc/abilities.php'; + if ( ! file_exists( $abilities ) ) { + $this->markTestSkipped( 'The Ipsum theme is not installed.' ); + } + require_once $abilities; + } + + public function tear_down() { + $this->registry_instance_property->setValue( null, $this->original_registry ); + if ( PHP_VERSION_ID < 80100 ) { + $this->registry_instance_property->setAccessible( false ); + } + + if ( get_stylesheet() !== $this->original_stylesheet ) { + switch_theme( $this->original_stylesheet ); + } + + parent::tear_down(); + } + + /** + * Tests that building the guide twice returns every theme pattern both times. + * + * @ticket 66631 + */ + public function test_returns_every_theme_pattern_when_called_twice() { + $expected = $this->switch_theme_and_register_patterns( 'ipsum' ); + + $this->assertSame( $expected, $this->get_design_guide_pattern_slugs(), 'The first call should return every theme pattern.' ); + $this->assertSame( $expected, $this->get_design_guide_pattern_slugs(), 'The second call should return every theme pattern.' ); + } + + /** + * Tests that every theme pattern is returned after something else reads all patterns. + * + * @ticket 66631 + */ + public function test_returns_every_theme_pattern_after_all_patterns_are_read() { + $expected = $this->switch_theme_and_register_patterns( 'ipsum' ); + + WP_Block_Patterns_Registry::get_instance()->get_all_registered(); + + $this->assertSame( $expected, $this->get_design_guide_pattern_slugs() ); + } + + /** + * Tests that every theme pattern is returned after one pattern is read, as the Pattern block does. + * + * @ticket 66631 + */ + public function test_returns_every_theme_pattern_after_one_pattern_is_read() { + $expected = $this->switch_theme_and_register_patterns( 'ipsum' ); + + WP_Block_Patterns_Registry::get_instance()->get_registered( $expected[0] ); + + $this->assertSame( $expected, $this->get_design_guide_pattern_slugs() ); + } + + /** + * Tests that patterns registered outside the theme are left out. + * + * @ticket 66631 + */ + public function test_leaves_out_patterns_from_outside_the_theme() { + $expected = $this->switch_theme_and_register_patterns( 'ipsum' ); + + register_block_pattern( + 'tests/not-from-the-theme', + array( + 'title' => 'Not From the Theme', + 'content' => 'Hello
', + ) + ); + + $this->assertSame( $expected, $this->get_design_guide_pattern_slugs() ); + } + + /** + * Tests that a child theme gets its own patterns and its parent's. + * + * @ticket 66631 + */ + public function test_returns_child_and_parent_theme_patterns() { + $expected = $this->switch_theme_and_register_patterns( 'block-theme-with-hooked-blocks-child' ); + + $this->assertContains( 'block-theme-with-hooked-blocks-child/child-pattern', $expected, 'The child theme should have a pattern of its own.' ); + $this->assertContains( 'block-theme-with-hooked-blocks/footer-default', $expected, 'The parent theme should have a pattern.' ); + $this->assertSame( $expected, $this->get_design_guide_pattern_slugs(), 'The theme pattern slugs to not match.' ); + } + + /** + * Switches to a theme and registers its patterns, as the `init` hook does. + * + * @param string $stylesheet The theme to switch to. + * @return string[] The slugs from the pattern files of the theme and its parent, sorted. + */ + private function switch_theme_and_register_patterns( $stylesheet ) { + switch_theme( $stylesheet ); + _register_theme_block_patterns(); + + // Read the slugs from the files, so the expected list doesn't depend on the code under test. + $slugs = array(); + foreach ( array_unique( array( get_stylesheet_directory(), get_template_directory() ) ) as $theme_directory ) { + foreach ( glob( $theme_directory . '/patterns/*.php' ) as $pattern_file ) { + $slugs[] = get_file_data( $pattern_file, array( 'slug' => 'Slug' ) )['slug']; + } + } + sort( $slugs ); + + $this->assertNotEmpty( $slugs, "The $stylesheet theme should have pattern files." ); + + return $slugs; + } + + /** + * Builds the patterns section of the design guide. + * + * @return string[] The slugs of the patterns in the guide, sorted. + */ + private function get_design_guide_pattern_slugs() { + $guide = ipsum_get_design_guide( array( 'fields' => array( 'patterns' ) ) ); + $slugs = wp_list_pluck( $guide['patterns'], 'slug' ); + sort( $slugs ); + + return $slugs; + } +} diff --git a/tests/phpunit/tests/theme/themeDir.php b/tests/phpunit/tests/theme/themeDir.php index cc7ca52a43cd2..5a57d154be1b5 100644 --- a/tests/phpunit/tests/theme/themeDir.php +++ b/tests/phpunit/tests/theme/themeDir.php @@ -190,6 +190,7 @@ public function test_theme_list() { 'Block Theme Post Content Default', 'Block Theme with defined Typography Fonts', 'Block Theme with Hooked Blocks', + 'Block Theme with Hooked Blocks Child Theme', 'Empty `fontFace` in theme.json - no webfonts defined', 'A theme with the Update URI header', );