mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-06-28 22:30:04 +00:00
Blocks: Introduce WP_Block_Type and WP_Block_Type_Registry classes.
These are the foundational classes allowing blocks to be registered and used throughout WordPress. This commit also includes the `has_block()` and `has_blocks()` functions, which are required for unit testing these classes. Merges [43742] from the 5.0 branch to trunk. Props adamsilverstein, danielbachhuber, desrosj. Fixes #45097. See #45109. git-svn-id: https://develop.svn.wordpress.org/trunk@44108 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -133,6 +133,7 @@ require dirname( __FILE__ ) . '/exceptions.php';
|
||||
require dirname( __FILE__ ) . '/utils.php';
|
||||
require dirname( __FILE__ ) . '/spy-rest-server.php';
|
||||
require dirname( __FILE__ ) . '/class-wp-rest-test-search-handler.php';
|
||||
require dirname( __FILE__ ) . '/class-wp-fake-block-type.php';
|
||||
|
||||
/**
|
||||
* A child class of the PHP test runner.
|
||||
|
||||
27
tests/phpunit/includes/class-wp-fake-block-type.php
Normal file
27
tests/phpunit/includes/class-wp-fake-block-type.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* WP_Fake_Block_Type for testing
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Blocks
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test class extending WP_Block_Type
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
class WP_Fake_Block_Type extends WP_Block_Type {
|
||||
|
||||
/**
|
||||
* Render the fake block.
|
||||
*
|
||||
* @param array $attributes Optional. Block attributes. Default empty array.
|
||||
* @param string $content Optional. Block content. Default empty string.
|
||||
* @return string Rendered block HTML.
|
||||
*/
|
||||
public function render( $attributes = array(), $content = '' ) {
|
||||
return '<div>' . $content . '</div>';
|
||||
}
|
||||
}
|
||||
191
tests/phpunit/tests/blocks/block-type-registry.php
Normal file
191
tests/phpunit/tests/blocks/block-type-registry.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
/**
|
||||
* WP_Block_Type_Registry Tests
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Blocks
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests for WP_Block_Type_Registry
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @group blocks
|
||||
*/
|
||||
class WP_Test_Block_Type_Registry extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Fake block type registry.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var WP_Block_Type_Registry
|
||||
*/
|
||||
private $registry = null;
|
||||
|
||||
/**
|
||||
* Set up each test method.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->registry = new WP_Block_Type_Registry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tear down each test method.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public function tearDown() {
|
||||
parent::tearDown();
|
||||
|
||||
$this->registry = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should reject numbers
|
||||
*
|
||||
* @ticket 45097
|
||||
*
|
||||
* @expectedIncorrectUsage WP_Block_Type_Registry::register
|
||||
*/
|
||||
public function test_invalid_non_string_names() {
|
||||
$result = $this->registry->register( 1, array() );
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Should reject blocks without a namespace
|
||||
*
|
||||
* @ticket 45097
|
||||
*
|
||||
* @expectedIncorrectUsage WP_Block_Type_Registry::register
|
||||
*/
|
||||
public function test_invalid_names_without_namespace() {
|
||||
$result = $this->registry->register( 'paragraph', array() );
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Should reject blocks with invalid characters
|
||||
*
|
||||
* @ticket 45097
|
||||
*
|
||||
* @expectedIncorrectUsage WP_Block_Type_Registry::register
|
||||
*/
|
||||
public function test_invalid_characters() {
|
||||
$result = $this->registry->register( 'still/_doing_it_wrong', array() );
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Should reject blocks with uppercase characters
|
||||
*
|
||||
* @ticket 45097
|
||||
*
|
||||
* @expectedIncorrectUsage WP_Block_Type_Registry::register
|
||||
*/
|
||||
public function test_uppercase_characters() {
|
||||
$result = $this->registry->register( 'Core/Paragraph', array() );
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Should accept valid block names
|
||||
*
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_register_block_type() {
|
||||
$name = 'core/paragraph';
|
||||
$settings = array(
|
||||
'icon' => 'editor-paragraph',
|
||||
);
|
||||
|
||||
$block_type = $this->registry->register( $name, $settings );
|
||||
$this->assertEquals( $name, $block_type->name );
|
||||
$this->assertEquals( $settings['icon'], $block_type->icon );
|
||||
$this->assertEquals( $block_type, $this->registry->get_registered( $name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Should fail to re-register the same block
|
||||
*
|
||||
* @ticket 45097
|
||||
*
|
||||
* @expectedIncorrectUsage WP_Block_Type_Registry::register
|
||||
*/
|
||||
public function test_register_block_type_twice() {
|
||||
$name = 'core/paragraph';
|
||||
$settings = array(
|
||||
'icon' => 'editor-paragraph',
|
||||
);
|
||||
|
||||
$result = $this->registry->register( $name, $settings );
|
||||
$this->assertNotFalse( $result );
|
||||
$result = $this->registry->register( $name, $settings );
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Should accept a WP_Block_Type instance
|
||||
*
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_register_block_type_instance() {
|
||||
$block_type = new WP_Fake_Block_Type( 'core/fake' );
|
||||
|
||||
$result = $this->registry->register( $block_type );
|
||||
$this->assertSame( $block_type, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregistering should fail if a block is not registered
|
||||
*
|
||||
* @ticket 45097
|
||||
*
|
||||
* @expectedIncorrectUsage WP_Block_Type_Registry::unregister
|
||||
*/
|
||||
public function test_unregister_not_registered_block() {
|
||||
$result = $this->registry->unregister( 'core/unregistered' );
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Should unregister existing blocks
|
||||
*
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_unregister_block_type() {
|
||||
$name = 'core/paragraph';
|
||||
$settings = array(
|
||||
'icon' => 'editor-paragraph',
|
||||
);
|
||||
|
||||
$this->registry->register( $name, $settings );
|
||||
$block_type = $this->registry->unregister( $name );
|
||||
$this->assertEquals( $name, $block_type->name );
|
||||
$this->assertEquals( $settings['icon'], $block_type->icon );
|
||||
$this->assertFalse( $this->registry->is_registered( $name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_get_all_registered() {
|
||||
$names = array( 'core/paragraph', 'core/image', 'core/blockquote' );
|
||||
$settings = array(
|
||||
'icon' => 'random',
|
||||
);
|
||||
|
||||
foreach ( $names as $name ) {
|
||||
$this->registry->register( $name, $settings );
|
||||
}
|
||||
|
||||
$registered = $this->registry->get_all_registered();
|
||||
$this->assertEqualSets( $names, array_keys( $registered ) );
|
||||
}
|
||||
}
|
||||
313
tests/phpunit/tests/blocks/block-type.php
Normal file
313
tests/phpunit/tests/blocks/block-type.php
Normal file
@@ -0,0 +1,313 @@
|
||||
<?php
|
||||
/**
|
||||
* WP_Block_Type Tests
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Blocks
|
||||
* @since 5.0.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tests for WP_Block_Type
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @group blocks
|
||||
*/
|
||||
class WP_Test_Block_Type extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* Editor user ID.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var int
|
||||
*/
|
||||
protected static $editor_user_id;
|
||||
|
||||
/**
|
||||
* ID for a post containing blocks.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var int
|
||||
*/
|
||||
protected static $post_with_blocks;
|
||||
|
||||
/**
|
||||
* ID for a post without blocks.
|
||||
*
|
||||
* @since 5.0.0
|
||||
* @var int
|
||||
*/
|
||||
protected static $post_without_blocks;
|
||||
|
||||
/**
|
||||
* Set up before class.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static function wpSetUpBeforeClass() {
|
||||
self::$editor_user_id = self::factory()->user->create(
|
||||
array(
|
||||
'role' => 'editor',
|
||||
)
|
||||
);
|
||||
|
||||
self::$post_with_blocks = self::factory()->post->create(
|
||||
array(
|
||||
'post_title' => 'Example',
|
||||
'post_content' => "<!-- wp:core/text {\"dropCap\":true} -->\n<p class=\"has-drop-cap\">Tester</p>\n<!-- /wp:core/text -->",
|
||||
)
|
||||
);
|
||||
|
||||
self::$post_without_blocks = self::factory()->post->create(
|
||||
array(
|
||||
'post_title' => 'Example',
|
||||
'post_content' => 'Tester',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_set_props() {
|
||||
$name = 'core/fake';
|
||||
$args = array(
|
||||
'render_callback' => array( $this, 'render_fake_block' ),
|
||||
'foo' => 'bar',
|
||||
);
|
||||
|
||||
$block_type = new WP_Block_Type( $name, $args );
|
||||
|
||||
$this->assertSame( $name, $block_type->name );
|
||||
$this->assertSame( $args['render_callback'], $block_type->render_callback );
|
||||
$this->assertSame( $args['foo'], $block_type->foo );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_render() {
|
||||
$attributes = array(
|
||||
'foo' => 'bar',
|
||||
'bar' => 'foo',
|
||||
);
|
||||
|
||||
$block_type = new WP_Block_Type(
|
||||
'core/fake',
|
||||
array(
|
||||
'render_callback' => array( $this, 'render_fake_block' ),
|
||||
)
|
||||
);
|
||||
$output = $block_type->render( $attributes );
|
||||
$this->assertEquals( $attributes, json_decode( $output, true ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_render_with_content() {
|
||||
$attributes = array(
|
||||
'foo' => 'bar',
|
||||
'bar' => 'foo',
|
||||
);
|
||||
|
||||
$content = 'baz';
|
||||
|
||||
$expected = array_merge( $attributes, array( '_content' => $content ) );
|
||||
|
||||
$block_type = new WP_Block_Type(
|
||||
'core/fake',
|
||||
array(
|
||||
'render_callback' => array( $this, 'render_fake_block_with_content' ),
|
||||
)
|
||||
);
|
||||
$output = $block_type->render( $attributes, $content );
|
||||
$this->assertEquals( $expected, json_decode( $output, true ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_render_for_static_block() {
|
||||
$block_type = new WP_Block_Type( 'core/fake', array() );
|
||||
$output = $block_type->render();
|
||||
|
||||
$this->assertEquals( '', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_is_dynamic_for_static_block() {
|
||||
$block_type = new WP_Block_Type( 'core/fake', array() );
|
||||
|
||||
$this->assertFalse( $block_type->is_dynamic() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_is_dynamic_for_dynamic_block() {
|
||||
$block_type = new WP_Block_Type(
|
||||
'core/fake',
|
||||
array(
|
||||
'render_callback' => array( $this, 'render_fake_block' ),
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertTrue( $block_type->is_dynamic() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_prepare_attributes() {
|
||||
$attributes = array(
|
||||
'correct' => 'include',
|
||||
'wrongType' => 5,
|
||||
'wrongTypeDefaulted' => 5,
|
||||
/* missingDefaulted */
|
||||
'undefined' => 'omit',
|
||||
);
|
||||
|
||||
$block_type = new WP_Block_Type(
|
||||
'core/fake',
|
||||
array(
|
||||
'attributes' => array(
|
||||
'correct' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'wrongType' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'wrongTypeDefaulted' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'defaulted',
|
||||
),
|
||||
'missingDefaulted' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'define',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$prepared_attributes = $block_type->prepare_attributes_for_render( $attributes );
|
||||
|
||||
$this->assertEquals(
|
||||
array(
|
||||
'correct' => 'include',
|
||||
'wrongType' => null,
|
||||
'wrongTypeDefaulted' => 'defaulted',
|
||||
'missingDefaulted' => 'define',
|
||||
),
|
||||
$prepared_attributes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_has_block_with_mixed_content() {
|
||||
$mixed_post_content = 'before' .
|
||||
'<!-- wp:core/fake --><!-- /wp:core/fake -->' .
|
||||
'<!-- wp:core/fake_atts {"value":"b1"} --><!-- /wp:core/fake_atts -->' .
|
||||
'<!-- wp:core/fake-child -->
|
||||
<p>testing the test</p>
|
||||
<!-- /wp:core/fake-child -->' .
|
||||
'between' .
|
||||
'<!-- wp:core/self-close-fake /-->' .
|
||||
'<!-- wp:custom/fake {"value":"b2"} /-->' .
|
||||
'after';
|
||||
|
||||
$this->assertTrue( has_block( 'core/fake', $mixed_post_content ) );
|
||||
|
||||
$this->assertTrue( has_block( 'core/fake_atts', $mixed_post_content ) );
|
||||
|
||||
$this->assertTrue( has_block( 'core/fake-child', $mixed_post_content ) );
|
||||
|
||||
$this->assertTrue( has_block( 'core/self-close-fake', $mixed_post_content ) );
|
||||
|
||||
$this->assertTrue( has_block( 'custom/fake', $mixed_post_content ) );
|
||||
|
||||
// checking for a partial block name should fail.
|
||||
$this->assertFalse( has_block( 'core/fak', $mixed_post_content ) );
|
||||
|
||||
// checking for a wrong namespace should fail.
|
||||
$this->assertFalse( has_block( 'custom/fake_atts', $mixed_post_content ) );
|
||||
|
||||
// checking for namespace only should not work. Or maybe ... ?
|
||||
$this->assertFalse( has_block( 'core', $mixed_post_content ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_has_block_with_invalid_content() {
|
||||
// some content with invalid HMTL comments and a single valid block.
|
||||
$invalid_content = 'before' .
|
||||
'<!- - wp:core/weird-space --><!-- /wp:core/weird-space -->' .
|
||||
'<!--wp:core/untrimmed-left --><!-- /wp:core/untrimmed -->' .
|
||||
'<!-- wp:core/fake --><!-- /wp:core/fake -->' .
|
||||
'<!-- wp:core/untrimmed-right--><!-- /wp:core/untrimmed2 -->' .
|
||||
'after';
|
||||
|
||||
$this->assertFalse( has_block( 'core/text', self::$post_without_blocks ) );
|
||||
|
||||
$this->assertFalse( has_block( 'core/weird-space', $invalid_content ) );
|
||||
|
||||
$this->assertFalse( has_block( 'core/untrimmed-left', $invalid_content ) );
|
||||
|
||||
$this->assertFalse( has_block( 'core/untrimmed-right', $invalid_content ) );
|
||||
|
||||
$this->assertTrue( has_block( 'core/fake', $invalid_content ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 45097
|
||||
*/
|
||||
public function test_post_has_block() {
|
||||
// should fail for a non-existent block `custom/fake`.
|
||||
$this->assertFalse( has_block( 'custom/fake', self::$post_with_blocks ) );
|
||||
|
||||
// this functions should not work without the second param until the $post global is set.
|
||||
$this->assertFalse( has_block( 'core/text' ) );
|
||||
$this->assertFalse( has_block( 'core/fake' ) );
|
||||
|
||||
global $post;
|
||||
$post = get_post( self::$post_with_blocks );
|
||||
|
||||
// check if the function correctly detects content from the $post global.
|
||||
$this->assertTrue( has_block( 'core/text' ) );
|
||||
// even if it detects a proper $post global it should still be false for a missing block.
|
||||
$this->assertFalse( has_block( 'core/fake' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a test block without content.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param array $attributes Block attributes. Default empty array.
|
||||
* @return string JSON encoded list of attributes.
|
||||
*/
|
||||
public function render_fake_block( $attributes ) {
|
||||
return json_encode( $attributes );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a test block with content.
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param array $attributes Block attributes. Default empty array.
|
||||
* @param string $content Block content. Default empty string.
|
||||
* @return string JSON encoded list of attributes.
|
||||
*/
|
||||
public function render_fake_block_with_content( $attributes, $content ) {
|
||||
$attributes['_content'] = $content;
|
||||
|
||||
return json_encode( $attributes );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user