diff --git a/.changeset/proud-fireants-buy.md b/.changeset/proud-fireants-buy.md new file mode 100644 index 00000000..f198e8ca --- /dev/null +++ b/.changeset/proud-fireants-buy.md @@ -0,0 +1,5 @@ +--- +"@wpengine/wp-graphql-content-blocks": patch +--- + +feat: Added a `CoreGroup` block class to fix an issue with a missing attribute `cssClassName` diff --git a/includes/Blocks/CoreGroup.php b/includes/Blocks/CoreGroup.php new file mode 100644 index 00000000..96187215 --- /dev/null +++ b/includes/Blocks/CoreGroup.php @@ -0,0 +1,28 @@ + [ + 'type' => 'string', + 'source' => 'attribute', + 'attribute' => 'class', + ], + ]; +} diff --git a/tests/unit/CoreGroupTest.php b/tests/unit/CoreGroupTest.php new file mode 100644 index 00000000..42ad890e --- /dev/null +++ b/tests/unit/CoreGroupTest.php @@ -0,0 +1,190 @@ +post_id = wp_insert_post( + [ + 'post_title' => 'Post Title', + 'post_content' => '', + 'post_status' => 'publish', + ] + ); + + \WPGraphQL::clear_schema(); + } + + public function tearDown(): void { + // your tear down methods here + wp_delete_post( $this->post_id, true ); + \WPGraphQL::clear_schema(); + + parent::tearDown(); + } + + /** + * Get the query for the CoreGroup block. + * + * @param string $attributes The attributes to add to query. + */ + public function query(): string { + return ' + fragment CoreGroupFragment on CoreGroup { + attributes { + align + backgroundColor + borderColor + className + cssClassName + fontFamily + fontSize + gradient + layout + lock + style + tagName + textColor + } + } + + query Post($id: ID!) { + post(id: $id, idType: DATABASE_ID) { + databaseId + editorBlocks(flat:true) { + apiVersion + blockEditorCategoryName + clientId + cssClassNames + innerBlocks { + name + } + name + parentClientId + renderedHtml + type + ...CoreGroupFragment + } + } + } + '; + } + + /** + * Test that the CoreGroup block is retrieved correctly. + * + * Covers the following attributes: + * - apiVersion + * - blockEditorCategoryName + * - clientId + * - cssClassNames + * - innerBlocks + * - name + * - parentClientId + * - renderedHtml + * - type + * - attributes + */ + + public function test_retrieve_core_group_fields_attributes(): void { + $block_content = << +
+

This is the left paragraph.

+ + + +

This is the right paragraph

+
+ + + +

This is an example page. It's different from a blog post because it will stay in one place and will show up in your site navigation (in most themes). Most people start with an About page that introduces them to potential site visitors. It might say something like this:

+ +HTML; + + $query = $this->query(); + + // Update the post content with the block content. + wp_update_post( + [ + 'ID' => $this->post_id, + 'post_content' => $block_content, + ] + ); + + $variables = [ + 'id' => $this->post_id, + ]; + + $actual = graphql( compact( 'query', 'variables' ) ); + $this->assertArrayNotHasKey( 'errors', $actual, 'There should not be any errors' ); + $this->assertArrayHasKey( 'data', $actual, 'The data key should be present' ); + $this->assertArrayHasKey( 'post', $actual['data'], 'The post key should be present' ); + $node = $actual['data']['post']; + + + // Verify that the ID of the first post matches the one we just created. + $this->assertEquals( $this->post_id, $node['databaseId'], 'The post ID should match' ); + $this->assertEquals( 'core/group', $node['editorBlocks'][0]['name'], 'The block name should match core/group' ); + $this->assertEquals( 'CoreGroup', $node['editorBlocks'][0]['type'], 'The block type should match CoreGroup' ); + $this->assertNotEmpty( $node['editorBlocks'], 'The node should have an array with the key editorBlocks which is not empty' ); + + // Check Block nodes + $block = $node['editorBlocks'][0]; + $this->assertNotEmpty( $block['apiVersion'], 'The apiVersion should be present' ); + $this->assertEquals( 'design', $block['blockEditorCategoryName'], 'The blockEditorCategoryName should be media' ); + $this->assertNotEmpty( $block['clientId'], 'The clientId should be present' ); + $this->assertNotEmpty( $block['cssClassNames'], 'The cssClassNames should be present' ); + $this->assertNotEmpty( $block['innerBlocks'], 'The innerBlocks should be an array' ); + $this->assertEmpty( $block['parentClientId'], 'There should be no parentClientId' ); + $this->assertNotEmpty( $block['renderedHtml'], 'The renderedHtml should be present' ); + + // Check child blocks + $clientId = $block['clientId']; + $childBlock1 = $node['editorBlocks'][1]; + $this->assertNotEmpty( $childBlock1, 'Child block 1 should be present' ); + $this->assertEquals( $clientId, $childBlock1['parentClientId'], 'Child block 1 parentClientId should match the parent block clientId' ); + $this->assertEquals('core/paragraph', $childBlock1['name'], 'Child block 1 should be a core/paragraph' ); + + $childBlock2 = $node['editorBlocks'][1]; + $this->assertNotEmpty( $childBlock2, 'Child block 2 should be present' ); + $this->assertEquals( $clientId, $childBlock1['parentClientId'], 'Child block 2 parentClientId should match the parent block clientId' ); + $this->assertEquals('core/paragraph', $childBlock1['name'], 'Child block 2 should be a core/paragraph' ); + + // Check attributes + $blockAttributes = $node['editorBlocks'][0]['attributes']; + $this->assertEquals(null, $blockAttributes['align']); + $this->assertEquals(null, $blockAttributes['backgroundColor']); + $this->assertEquals(null, $blockAttributes['borderColor']); + $this->assertEquals('test-group-class is-style-default', $blockAttributes['className']); + $this->assertStringContainsString('wp-block-group test-group-class is-style-default', $blockAttributes['cssClassName']); // Class name varies slightly between WP versions + $this->assertEquals(null, $blockAttributes['fontFamily']); + $this->assertEquals(null, $blockAttributes['fontSize']); + $this->assertEquals("{\"type\":\"flex\",\"flexWrap\":\"wrap\",\"justifyContent\":\"center\"}", $blockAttributes['layout']); + $this->assertEquals(null, $blockAttributes['style']); + $this->assertEquals('header', $blockAttributes['tagName']); + $this->assertEquals(null, $blockAttributes['textColor']); + } +}