From adf384a7e4bdb3a33a22d4d59efb03b94b032f51 Mon Sep 17 00:00:00 2001 From: Ta5r Date: Mon, 16 Sep 2024 19:28:39 +0530 Subject: [PATCH 1/9] dev : backfilling tests for refactored and updated content blocks resolver. --- tests/unit/ContentBlocksResolverTest.php | 67 ++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/unit/ContentBlocksResolverTest.php b/tests/unit/ContentBlocksResolverTest.php index 5920d69f..969cb873 100644 --- a/tests/unit/ContentBlocksResolverTest.php +++ b/tests/unit/ContentBlocksResolverTest.php @@ -136,4 +136,71 @@ static function ( $parsed_block ) { $this->assertEquals( 4, count( $parsed_blocks ) ); $this->assertEquals( $allowed, $actual_block_names ); } + + public function test_pre_resolved_blocks_filter_returns_non_null() { + add_filter( 'wpgraphql_content_blocks_pre_resolve_blocks', function( $blocks, $node, $args, $allowed_block_names ) { + return [ [ 'blockName' => 'core/paragraph', 'attrs' => [ 'content' => 'Test content' ] ] ]; + }, 10, 4); + + $post_id = self::factory()->post->create( [ 'post_content' => '' ] ); + $post = new Post( get_post( $post_id ) ); + + $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); + // The filter should return a block. + $this->assertCount( 1, $resolved_blocks ); + $this->assertEquals( 'core/paragraph', $resolved_blocks[0][ 'blockName' ] ); + } + + public function test_content_retrieved_from_post_node() { + $post_id = self::factory()->post->create( [ + 'post_content' => '

Content

' + ] ); + $post = new Post( get_post( $post_id ) ); + $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); + + // The block should be resolved from the post node. + $this->assertCount( 1, $resolved_blocks ); + $this->assertEquals( 'core/paragraph', $resolved_blocks[0][ 'blockName' ] ); + } + + public function test_returns_empty_array_for_empty_content() { + $post_id = self::factory()->post->create( [ 'post_content' => '' ] ); + $post = new Post( get_post( $post_id ) ); + + $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); + + // The block should be resolved from the post node. + $this->assertIsArray( $resolved_blocks ); + $this->assertEmpty( $resolved_blocks ); + } + + public function test_filters_allowed_blocks() { + $post_id = self::factory()->post->create( [ + 'post_content' => '

Content

' . + '

Heading

' + ] ); + $post = new Post( get_post( $post_id ) ); + $resolved_blocks = $this->instance->resolve_content_blocks( $post, [], [ 'core/paragraph' ] ); + + // The block should be resolved from the post node. + $this->assertCount( 1, $resolved_blocks ); + $this->assertEquals( 'core/paragraph', $resolved_blocks[0][ 'blockName' ] ); + } + + public function test_filters_after_resolving_blocks() { + add_filter( 'wpgraphql_content_blocks_resolve_blocks', function( $blocks, $node, $args, $allowed_block_names ) { + return [ [ 'blockName' => 'core/test-filter' ] ]; + }, 10, 4 ); + + $post_id = self::factory()->post->create( [ + 'post_content' => '

Content

' + ] ); + $post = new Post( get_post( $post_id ) ); + + $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); + + // The block should be resolved from the post node. + $this->assertCount( 1, $resolved_blocks ); + $this->assertEquals( 'core/test-filter', $resolved_blocks[0][ 'blockName' ] ); + } } From 1025436168a76ac435aee5e35e2ed0ce27f7536e Mon Sep 17 00:00:00 2001 From: Ta5r Date: Mon, 16 Sep 2024 19:44:40 +0530 Subject: [PATCH 2/9] stash progress --- tests/unit/ContentBlocksResolverTest.php | 61 ++++++++++++++++-------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/tests/unit/ContentBlocksResolverTest.php b/tests/unit/ContentBlocksResolverTest.php index 969cb873..f683a8da 100644 --- a/tests/unit/ContentBlocksResolverTest.php +++ b/tests/unit/ContentBlocksResolverTest.php @@ -138,9 +138,19 @@ static function ( $parsed_block ) { } public function test_pre_resolved_blocks_filter_returns_non_null() { - add_filter( 'wpgraphql_content_blocks_pre_resolve_blocks', function( $blocks, $node, $args, $allowed_block_names ) { - return [ [ 'blockName' => 'core/paragraph', 'attrs' => [ 'content' => 'Test content' ] ] ]; - }, 10, 4); + add_filter( + 'wpgraphql_content_blocks_pre_resolve_blocks', + static function ( $blocks, $node, $args, $allowed_block_names ) { + return [ + [ + 'blockName' => 'core/paragraph', + 'attrs' => [ 'content' => 'Test content' ], + ], + ]; + }, + 10, + 4 + ); $post_id = self::factory()->post->create( [ 'post_content' => '' ] ); $post = new Post( get_post( $post_id ) ); @@ -148,19 +158,21 @@ public function test_pre_resolved_blocks_filter_returns_non_null() { $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); // The filter should return a block. $this->assertCount( 1, $resolved_blocks ); - $this->assertEquals( 'core/paragraph', $resolved_blocks[0][ 'blockName' ] ); + $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); } public function test_content_retrieved_from_post_node() { - $post_id = self::factory()->post->create( [ - 'post_content' => '

Content

' - ] ); + $post_id = self::factory()->post->create( + [ + 'post_content' => '

Content

', + ] + ); $post = new Post( get_post( $post_id ) ); $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); // The block should be resolved from the post node. $this->assertCount( 1, $resolved_blocks ); - $this->assertEquals( 'core/paragraph', $resolved_blocks[0][ 'blockName' ] ); + $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); } public function test_returns_empty_array_for_empty_content() { @@ -175,32 +187,41 @@ public function test_returns_empty_array_for_empty_content() { } public function test_filters_allowed_blocks() { - $post_id = self::factory()->post->create( [ - 'post_content' => '

Content

' . - '

Heading

' - ] ); + $post_id = self::factory()->post->create( + [ + 'post_content' => '

Content

' . + '

Heading

', + ] + ); $post = new Post( get_post( $post_id ) ); $resolved_blocks = $this->instance->resolve_content_blocks( $post, [], [ 'core/paragraph' ] ); // The block should be resolved from the post node. $this->assertCount( 1, $resolved_blocks ); - $this->assertEquals( 'core/paragraph', $resolved_blocks[0][ 'blockName' ] ); + $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); } public function test_filters_after_resolving_blocks() { - add_filter( 'wpgraphql_content_blocks_resolve_blocks', function( $blocks, $node, $args, $allowed_block_names ) { - return [ [ 'blockName' => 'core/test-filter' ] ]; - }, 10, 4 ); + add_filter( + 'wpgraphql_content_blocks_resolve_blocks', + static function ( $blocks, $node, $args, $allowed_block_names ) { + return [ [ 'blockName' => 'core/test-filter' ] ]; + }, + 10, + 4 + ); - $post_id = self::factory()->post->create( [ - 'post_content' => '

Content

' - ] ); + $post_id = self::factory()->post->create( + [ + 'post_content' => '

Content

', + ] + ); $post = new Post( get_post( $post_id ) ); $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); // The block should be resolved from the post node. $this->assertCount( 1, $resolved_blocks ); - $this->assertEquals( 'core/test-filter', $resolved_blocks[0][ 'blockName' ] ); + $this->assertEquals( 'core/test-filter', $resolved_blocks[0]['blockName'] ); } } From 9c2103eba9466404911c1bdc3dcdb030e2684383 Mon Sep 17 00:00:00 2001 From: Ta5r Date: Mon, 16 Sep 2024 20:00:11 +0530 Subject: [PATCH 3/9] docs : Added doc blocks for test cases. --- tests/unit/ContentBlocksResolverTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/unit/ContentBlocksResolverTest.php b/tests/unit/ContentBlocksResolverTest.php index f683a8da..e8af8d85 100644 --- a/tests/unit/ContentBlocksResolverTest.php +++ b/tests/unit/ContentBlocksResolverTest.php @@ -137,6 +137,9 @@ static function ( $parsed_block ) { $this->assertEquals( $allowed, $actual_block_names ); } + /** + * Test the wpgraphql_content_blocks_pre_resolve_blocks filter. + */ public function test_pre_resolved_blocks_filter_returns_non_null() { add_filter( 'wpgraphql_content_blocks_pre_resolve_blocks', @@ -159,8 +162,12 @@ static function ( $blocks, $node, $args, $allowed_block_names ) { // The filter should return a block. $this->assertCount( 1, $resolved_blocks ); $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); + $this->assertEquals( 'Test content', $resolved_blocks[0]['attrs']['content'] ); } + /** + * Tests content retrieval from a post node. + */ public function test_content_retrieved_from_post_node() { $post_id = self::factory()->post->create( [ @@ -175,6 +182,9 @@ public function test_content_retrieved_from_post_node() { $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); } + /** + * Tests that an empty array is returned when the post content is empty. + */ public function test_returns_empty_array_for_empty_content() { $post_id = self::factory()->post->create( [ 'post_content' => '' ] ); $post = new Post( get_post( $post_id ) ); @@ -186,6 +196,9 @@ public function test_returns_empty_array_for_empty_content() { $this->assertEmpty( $resolved_blocks ); } + /** + * Tests that the wpgraphql_content_blocks_allowed_blocks filter is applied. + */ public function test_filters_allowed_blocks() { $post_id = self::factory()->post->create( [ @@ -201,6 +214,9 @@ public function test_filters_allowed_blocks() { $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); } + /** + * Tests that the wpgraphql_content_blocks_resolve_blocks filter is applied. + */ public function test_filters_after_resolving_blocks() { add_filter( 'wpgraphql_content_blocks_resolve_blocks', From 08e55cdce04bd427be4ae9ffbc2c9496c5260b31 Mon Sep 17 00:00:00 2001 From: Ta5r Date: Thu, 19 Sep 2024 16:40:19 +0530 Subject: [PATCH 4/9] stash : progress --- tests/unit/ContentBlocksResolverTest.php | 237 ++++++++++++++++++++++- 1 file changed, 231 insertions(+), 6 deletions(-) diff --git a/tests/unit/ContentBlocksResolverTest.php b/tests/unit/ContentBlocksResolverTest.php index e8af8d85..576126ce 100644 --- a/tests/unit/ContentBlocksResolverTest.php +++ b/tests/unit/ContentBlocksResolverTest.php @@ -92,6 +92,10 @@ public function tearDown(): void { wp_delete_post( $this->post_id, true ); wp_delete_post( $this->reusable_post_id, true ); wp_delete_post( $this->reusable_block_id, true ); + + // Clean up the filter. + remove_all_filters( 'wpgraphql_content_blocks_pre_resolve_blocks' ); + remove_all_filters( 'wpgraphql_content_blocks_resolve_blocks' ); } public function test_resolve_content_blocks_resolves_reusable_blocks() { @@ -163,6 +167,9 @@ static function ( $blocks, $node, $args, $allowed_block_names ) { $this->assertCount( 1, $resolved_blocks ); $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); $this->assertEquals( 'Test content', $resolved_blocks[0]['attrs']['content'] ); + + // Clean up by deleting the created post. + wp_delete_post( $post_id, true ); } /** @@ -227,12 +234,7 @@ static function ( $blocks, $node, $args, $allowed_block_names ) { 4 ); - $post_id = self::factory()->post->create( - [ - 'post_content' => '

Content

', - ] - ); - $post = new Post( get_post( $post_id ) ); + $post = new Post( get_post( $this->post_id ) ); $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); @@ -240,4 +242,227 @@ static function ( $blocks, $node, $args, $allowed_block_names ) { $this->assertCount( 1, $resolved_blocks ); $this->assertEquals( 'core/test-filter', $resolved_blocks[0]['blockName'] ); } + + public function test_inner_blocks_have_correct_parent_client_id() { + // Set up post content with nested blocks + $post_id = self::factory()->post->create( + [ + 'post_content' => ' + +
+ +
+ +

Heading

+ + +

Paragraph

+ +
+ + +
+ +

Heading

+ + +

Paragraph

+ +
+ +
+ + ', + ] + ); + $post = new Post( get_post( $post_id ) ); + + // Resolve blocks in flat mode + $resolved_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); + + // Create a mapping of clientIds to parentClientIds + $parent_map = []; + + // Loop through resolved blocks to populate parent map. + foreach ( $resolved_blocks as $block ) { + if ( isset( $block['parentClientId'] ) ) { + $parent_map[ $block['clientId'] ] = $block['parentClientId']; + } + else { + $parent_map[ $block['clientId'] ] = null; + } + } + + // Validate parent-child relationships + foreach ( $resolved_blocks as $block ) { + if ( isset( $block['parentClientId'] ) ) { + + // Ensure that the parentClientId points to a valid block + $this->assertArrayHasKey( $block['parentClientId'], $parent_map ); + } + } + + // Now compare nested and flat structures + $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); + + // Create a helper function to compare nested structure with flat + // $this->assertNestedBlocksMatchFlat($nested_blocks, $resolved_blocks); + + // Resolve blocks in nested mode + // $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); + // // Resolve blocks in flat mode + // $flat_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); + + // // Convert nested blocks to flat structure for comparison + // $transformed_nested_blocks = $this->transformNestedToFlat($nested_blocks); + + // // Assert that the transformed nested structure matches the flat structure + // $this->assertEquals($transformed_nested_blocks, $flat_blocks); + + // Resolve blocks in nested mode + $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); + // Resolve blocks in flat mode + $flat_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); + + // Convert nested blocks to flat structure for comparison + $transformed_nested_blocks = $this->transformNestedToFlat($nested_blocks); + + // Normalize both block arrays for comparison + $normalized_nested_blocks = $this->normalizeBlocks($transformed_nested_blocks); + $normalized_flat_blocks = $this->normalizeBlocks($flat_blocks); + + // Assert that the normalized structures match + $this->assertEquals($normalized_nested_blocks, $normalized_flat_blocks); + } + + + // Helper function to transform nested blocks into flat structure + protected function transformNestedToFlat(array $nested_blocks) { + $flat_blocks = []; + + foreach ($nested_blocks as $block) { + $flat_blocks[] = $block; + if (!empty($block['innerBlocks'])) { + $flat_blocks = array_merge($flat_blocks, $this->transformNestedToFlat($block['innerBlocks'])); + } + } + + return $flat_blocks; + } + + +// Helper function to normalize blocks by removing 'clientId' +protected function normalizeBlocks(array $blocks) { + return array_map(function($block) { + // Remove 'clientId' and 'parentClientId' from comparison + unset($block['clientId']); + unset($block['parentClientId']); + + if (!empty($block['innerBlocks'])) { + $block['innerBlocks'] = $this->normalizeBlocks($block['innerBlocks']); + } + + return $block; + }, $blocks); +} + + + // Helper function to validate nested blocks + // protected function assertNestedBlocksMatchFlat(array $nested_blocks, array $flat_blocks) { + + + // foreach ($nested_blocks as $block) { + // if (!empty($block['innerBlocks'])) { + // foreach ($block['innerBlocks'] as $inner_block) { + + // // Find the corresponding flat block + // $flat_block = array_filter($flat_blocks, function ($flat) use ($inner_block) { + + // return $flat['clientId'] === $inner_block['clientId']; + // }); + + + // // Assert that the parentClientId in flat block matches the parent's clientId + // $this->assertNotEmpty($flat_block); + // $flat_block = array_shift($flat_block); // Get the first matched block + // $this->assertEquals($block['clientId'], $flat_block['parentClientId']); + + // // Recursively check nested blocks + // $this->assertNestedBlocksMatchFlat($inner_block['innerBlocks'], $flat_blocks); + // } + // } + // } + // } + + + // public function test_inner_blocks_have_correct_parent_client_id_x() { + // $post_id = self::factory()->post->create( + // [ + // 'post_content' => ' + // + //
+ // + //
+ // + //

Heading

+ // + // + //

Paragraph

+ // + //
+ // + // + //
+ // + //

Heading

+ // + // + //

Paragraph

+ // + //
+ // + //
+ // + // ', + // ] + // ); + // $post = new Post( get_post( $post_id ) ); + + // // Resolving blocks in "flat" mode. + // $resolved_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); + + // // Checking that the are blocks resolved. + // $this->assertNotEmpty( $resolved_blocks ); + + // // Creating a mapping of clientIds to block structures for flat checking. + // $client_id_map = []; + + // // Looping through resolved blocks to verify parentClientId assignment. + // foreach ( $resolved_blocks as $block ) { + // if ( ! empty( $block['innerBlocks'] ) ) { + // foreach ( $block['innerBlocks'] as $inner_block ) { + // // Verify that inner blocks have the correct parentClientId. + // $this->assertEquals( $block['clientId'], $inner_block['parentClientId'] ); + + // // Add to client_id_map for later comparison. + // $client_id_map[ $inner_block['clientId'] ] = $inner_block; + // } + // } + // } + + // // Resolve blocks in "non-flat" mode. + // $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); + + // // Compare flat and non-flat structures. + // foreach ( $nested_blocks as $block ) { + // if ( ! empty( $block['innerBlocks'] ) ) { + // foreach ( $block['innerBlocks'] as $inner_block ) { + // // Compare non-flat inner block with the corresponding flat block. + // $this->assertArrayHasKey( $inner_block['clientId'], $client_id_map ); + // $this->assertEquals( $client_id_map[ $inner_block['clientId'] ], $inner_block ); + // } + // } + // } + // } + } From fcde1f287b095eeed886f60377517f58423fe835 Mon Sep 17 00:00:00 2001 From: Ta5r Date: Thu, 19 Sep 2024 19:05:13 +0530 Subject: [PATCH 5/9] chore: test comment --- tests/unit/ContentBlocksResolverTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/ContentBlocksResolverTest.php b/tests/unit/ContentBlocksResolverTest.php index 576126ce..f0c58322 100644 --- a/tests/unit/ContentBlocksResolverTest.php +++ b/tests/unit/ContentBlocksResolverTest.php @@ -13,7 +13,7 @@ final class ContentBlocksResolverTest extends PluginTestCase { public function setUp(): void { parent::setUp(); - + // Test comment. $this->reusable_block_id = wp_insert_post( [ 'post_title' => 'Reusable Block', From 4eae890ee649f507158c9a3017729a422a34a104 Mon Sep 17 00:00:00 2001 From: Ta5r Date: Mon, 16 Sep 2024 19:44:40 +0530 Subject: [PATCH 6/9] stash progress --- tests/unit/ContentBlocksResolverTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/ContentBlocksResolverTest.php b/tests/unit/ContentBlocksResolverTest.php index f0c58322..037f3955 100644 --- a/tests/unit/ContentBlocksResolverTest.php +++ b/tests/unit/ContentBlocksResolverTest.php @@ -13,7 +13,6 @@ final class ContentBlocksResolverTest extends PluginTestCase { public function setUp(): void { parent::setUp(); - // Test comment. $this->reusable_block_id = wp_insert_post( [ 'post_title' => 'Reusable Block', From 5ca9509c7ea94973e314adfd12246d6529096320 Mon Sep 17 00:00:00 2001 From: Ta5r Date: Fri, 20 Sep 2024 22:38:41 +0530 Subject: [PATCH 7/9] chore : cleanup --- tests/unit/ContentBlocksResolverTest.php | 210 ++++++----------------- 1 file changed, 51 insertions(+), 159 deletions(-) diff --git a/tests/unit/ContentBlocksResolverTest.php b/tests/unit/ContentBlocksResolverTest.php index 037f3955..46456e72 100644 --- a/tests/unit/ContentBlocksResolverTest.php +++ b/tests/unit/ContentBlocksResolverTest.php @@ -13,6 +13,7 @@ final class ContentBlocksResolverTest extends PluginTestCase { public function setUp(): void { parent::setUp(); + $this->reusable_block_id = wp_insert_post( [ 'post_title' => 'Reusable Block', @@ -243,7 +244,7 @@ static function ( $blocks, $node, $args, $allowed_block_names ) { } public function test_inner_blocks_have_correct_parent_client_id() { - // Set up post content with nested blocks + $post_id = self::factory()->post->create( [ 'post_content' => ' @@ -274,194 +275,85 @@ public function test_inner_blocks_have_correct_parent_client_id() { ', ] ); - $post = new Post( get_post( $post_id ) ); - - // Resolve blocks in flat mode + $post = new Post( get_post( $post_id ) ); + + // Resolve blocks in flat mode. $resolved_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); - // Create a mapping of clientIds to parentClientIds + // Create a mapping of clientIds to parentClientIds. $parent_map = []; - + // Loop through resolved blocks to populate parent map. foreach ( $resolved_blocks as $block ) { if ( isset( $block['parentClientId'] ) ) { $parent_map[ $block['clientId'] ] = $block['parentClientId']; - } - else { + } else { $parent_map[ $block['clientId'] ] = null; } } - - // Validate parent-child relationships + + // Validate parent-child relationships. foreach ( $resolved_blocks as $block ) { if ( isset( $block['parentClientId'] ) ) { - // Ensure that the parentClientId points to a valid block + // Ensure that the parentClientId points to a valid block. $this->assertArrayHasKey( $block['parentClientId'], $parent_map ); } } - - // Now compare nested and flat structures + + // Now compare nested and flat structures. $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); - // Create a helper function to compare nested structure with flat - // $this->assertNestedBlocksMatchFlat($nested_blocks, $resolved_blocks); - - // Resolve blocks in nested mode - // $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); - // // Resolve blocks in flat mode - // $flat_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); - - // // Convert nested blocks to flat structure for comparison - // $transformed_nested_blocks = $this->transformNestedToFlat($nested_blocks); - - // // Assert that the transformed nested structure matches the flat structure - // $this->assertEquals($transformed_nested_blocks, $flat_blocks); - - // Resolve blocks in nested mode + // Resolve blocks in nested mode. $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); - // Resolve blocks in flat mode + // Resolve blocks in flat mode. $flat_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); - - // Convert nested blocks to flat structure for comparison - $transformed_nested_blocks = $this->transformNestedToFlat($nested_blocks); - - // Normalize both block arrays for comparison - $normalized_nested_blocks = $this->normalizeBlocks($transformed_nested_blocks); - $normalized_flat_blocks = $this->normalizeBlocks($flat_blocks); - - // Assert that the normalized structures match - $this->assertEquals($normalized_nested_blocks, $normalized_flat_blocks); - } + // Convert nested blocks to flat structure for comparison. + $transformed_nested_blocks = $this->transformNestedToFlat( $nested_blocks ); + + // Normalize both block arrays for comparison. + $normalized_nested_blocks = $this->normalizeBlocks( $transformed_nested_blocks ); + $normalized_flat_blocks = $this->normalizeBlocks( $flat_blocks ); + + // Assert that the normalized structures match. + $this->assertEquals( $normalized_nested_blocks, $normalized_flat_blocks ); + } - // Helper function to transform nested blocks into flat structure - protected function transformNestedToFlat(array $nested_blocks) { + /** + * Helper function to transform nested blocks to flat structure. + */ + protected function transformNestedToFlat( array $nested_blocks ) { $flat_blocks = []; - - foreach ($nested_blocks as $block) { + + foreach ( $nested_blocks as $block ) { $flat_blocks[] = $block; - if (!empty($block['innerBlocks'])) { - $flat_blocks = array_merge($flat_blocks, $this->transformNestedToFlat($block['innerBlocks'])); + if ( ! empty( $block['innerBlocks'] ) ) { + $flat_blocks = array_merge( $flat_blocks, $this->transformNestedToFlat( $block['innerBlocks'] ) ); } } - + return $flat_blocks; } + /** + * Helper function to normalize block structures for comparison. + */ + protected function normalizeBlocks( array $blocks ) { + return array_map( + function ( $block ) { -// Helper function to normalize blocks by removing 'clientId' -protected function normalizeBlocks(array $blocks) { - return array_map(function($block) { - // Remove 'clientId' and 'parentClientId' from comparison - unset($block['clientId']); - unset($block['parentClientId']); - - if (!empty($block['innerBlocks'])) { - $block['innerBlocks'] = $this->normalizeBlocks($block['innerBlocks']); - } + // Remove 'clientId' and 'parentClientId' from comparison. + unset( $block['clientId'] ); + unset( $block['parentClientId'] ); - return $block; - }, $blocks); -} + if ( ! empty( $block['innerBlocks'] ) ) { + $block['innerBlocks'] = $this->normalizeBlocks( $block['innerBlocks'] ); + } - - // Helper function to validate nested blocks - // protected function assertNestedBlocksMatchFlat(array $nested_blocks, array $flat_blocks) { - - - // foreach ($nested_blocks as $block) { - // if (!empty($block['innerBlocks'])) { - // foreach ($block['innerBlocks'] as $inner_block) { - - // // Find the corresponding flat block - // $flat_block = array_filter($flat_blocks, function ($flat) use ($inner_block) { - - // return $flat['clientId'] === $inner_block['clientId']; - // }); - - - // // Assert that the parentClientId in flat block matches the parent's clientId - // $this->assertNotEmpty($flat_block); - // $flat_block = array_shift($flat_block); // Get the first matched block - // $this->assertEquals($block['clientId'], $flat_block['parentClientId']); - - // // Recursively check nested blocks - // $this->assertNestedBlocksMatchFlat($inner_block['innerBlocks'], $flat_blocks); - // } - // } - // } - // } - - - // public function test_inner_blocks_have_correct_parent_client_id_x() { - // $post_id = self::factory()->post->create( - // [ - // 'post_content' => ' - // - //
- // - //
- // - //

Heading

- // - // - //

Paragraph

- // - //
- // - // - //
- // - //

Heading

- // - // - //

Paragraph

- // - //
- // - //
- // - // ', - // ] - // ); - // $post = new Post( get_post( $post_id ) ); - - // // Resolving blocks in "flat" mode. - // $resolved_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); - - // // Checking that the are blocks resolved. - // $this->assertNotEmpty( $resolved_blocks ); - - // // Creating a mapping of clientIds to block structures for flat checking. - // $client_id_map = []; - - // // Looping through resolved blocks to verify parentClientId assignment. - // foreach ( $resolved_blocks as $block ) { - // if ( ! empty( $block['innerBlocks'] ) ) { - // foreach ( $block['innerBlocks'] as $inner_block ) { - // // Verify that inner blocks have the correct parentClientId. - // $this->assertEquals( $block['clientId'], $inner_block['parentClientId'] ); - - // // Add to client_id_map for later comparison. - // $client_id_map[ $inner_block['clientId'] ] = $inner_block; - // } - // } - // } - - // // Resolve blocks in "non-flat" mode. - // $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); - - // // Compare flat and non-flat structures. - // foreach ( $nested_blocks as $block ) { - // if ( ! empty( $block['innerBlocks'] ) ) { - // foreach ( $block['innerBlocks'] as $inner_block ) { - // // Compare non-flat inner block with the corresponding flat block. - // $this->assertArrayHasKey( $inner_block['clientId'], $client_id_map ); - // $this->assertEquals( $client_id_map[ $inner_block['clientId'] ], $inner_block ); - // } - // } - // } - // } - + return $block; + }, + $blocks + ); + } } From c5f04104b3fa8cbdec5732d476c4369a83e1d753 Mon Sep 17 00:00:00 2001 From: DDEV User Date: Sat, 21 Sep 2024 17:33:50 +0000 Subject: [PATCH 8/9] chore: cleanup and refactor --- tests/unit/ContentBlocksResolverTest.php | 262 +++++++++++------------ 1 file changed, 126 insertions(+), 136 deletions(-) diff --git a/tests/unit/ContentBlocksResolverTest.php b/tests/unit/ContentBlocksResolverTest.php index 46456e72..6dc35f2c 100644 --- a/tests/unit/ContentBlocksResolverTest.php +++ b/tests/unit/ContentBlocksResolverTest.php @@ -92,10 +92,6 @@ public function tearDown(): void { wp_delete_post( $this->post_id, true ); wp_delete_post( $this->reusable_post_id, true ); wp_delete_post( $this->reusable_block_id, true ); - - // Clean up the filter. - remove_all_filters( 'wpgraphql_content_blocks_pre_resolve_blocks' ); - remove_all_filters( 'wpgraphql_content_blocks_resolve_blocks' ); } public function test_resolve_content_blocks_resolves_reusable_blocks() { @@ -147,7 +143,7 @@ static function ( $parsed_block ) { public function test_pre_resolved_blocks_filter_returns_non_null() { add_filter( 'wpgraphql_content_blocks_pre_resolve_blocks', - static function ( $blocks, $node, $args, $allowed_block_names ) { + static function () { return [ [ 'blockName' => 'core/paragraph', @@ -156,11 +152,9 @@ static function ( $blocks, $node, $args, $allowed_block_names ) { ]; }, 10, - 4 ); - $post_id = self::factory()->post->create( [ 'post_content' => '' ] ); - $post = new Post( get_post( $post_id ) ); + $post = new Post( get_post( $this->post_id ) ); $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); // The filter should return a block. @@ -168,25 +162,8 @@ static function ( $blocks, $node, $args, $allowed_block_names ) { $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); $this->assertEquals( 'Test content', $resolved_blocks[0]['attrs']['content'] ); - // Clean up by deleting the created post. - wp_delete_post( $post_id, true ); - } - - /** - * Tests content retrieval from a post node. - */ - public function test_content_retrieved_from_post_node() { - $post_id = self::factory()->post->create( - [ - 'post_content' => '

Content

', - ] - ); - $post = new Post( get_post( $post_id ) ); - $resolved_blocks = $this->instance->resolve_content_blocks( $post, [] ); - - // The block should be resolved from the post node. - $this->assertCount( 1, $resolved_blocks ); - $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); + // Cleanup. + remove_all_filters( 'wpgraphql_content_blocks_pre_resolve_blocks' ); } /** @@ -201,30 +178,15 @@ public function test_returns_empty_array_for_empty_content() { // The block should be resolved from the post node. $this->assertIsArray( $resolved_blocks ); $this->assertEmpty( $resolved_blocks ); - } - /** - * Tests that the wpgraphql_content_blocks_allowed_blocks filter is applied. - */ - public function test_filters_allowed_blocks() { - $post_id = self::factory()->post->create( - [ - 'post_content' => '

Content

' . - '

Heading

', - ] - ); - $post = new Post( get_post( $post_id ) ); - $resolved_blocks = $this->instance->resolve_content_blocks( $post, [], [ 'core/paragraph' ] ); - - // The block should be resolved from the post node. - $this->assertCount( 1, $resolved_blocks ); - $this->assertEquals( 'core/paragraph', $resolved_blocks[0]['blockName'] ); + // Cleanup. + wp_delete_post( $post_id, true ); } /** * Tests that the wpgraphql_content_blocks_resolve_blocks filter is applied. */ - public function test_filters_after_resolving_blocks() { + public function test_filters_wpgraphql_content_blocks_resolve_blocks() { add_filter( 'wpgraphql_content_blocks_resolve_blocks', static function ( $blocks, $node, $args, $allowed_block_names ) { @@ -241,119 +203,147 @@ static function ( $blocks, $node, $args, $allowed_block_names ) { // The block should be resolved from the post node. $this->assertCount( 1, $resolved_blocks ); $this->assertEquals( 'core/test-filter', $resolved_blocks[0]['blockName'] ); - } - public function test_inner_blocks_have_correct_parent_client_id() { + // Cleanup. + remove_all_filters( 'wpgraphql_content_blocks_resolve_blocks' ); + } - $post_id = self::factory()->post->create( + /** + * Tests that flat and nested blocks are resolved correctly. + */ + public function test_inner_blocks() { + $post_content = ' + +
+ +
+ +

Heading

+ + +

Paragraph

+ +
+ + +
+ +

Heading

+ + +

Paragraph

+ +
+ +
+ '; + + wp_update_post( [ - 'post_content' => ' - -
- -
- -

Heading

- - -

Paragraph

- -
- - -
- -

Heading

- - -

Paragraph

- -
- -
- - ', + 'ID' => $this->post_id, + 'post_content' => $post_content, ] ); - $post = new Post( get_post( $post_id ) ); - - // Resolve blocks in flat mode. - $resolved_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); - - // Create a mapping of clientIds to parentClientIds. - $parent_map = []; - - // Loop through resolved blocks to populate parent map. - foreach ( $resolved_blocks as $block ) { - if ( isset( $block['parentClientId'] ) ) { - $parent_map[ $block['clientId'] ] = $block['parentClientId']; - } else { - $parent_map[ $block['clientId'] ] = null; - } - } - // Validate parent-child relationships. - foreach ( $resolved_blocks as $block ) { - if ( isset( $block['parentClientId'] ) ) { + $post = new Post( get_post( $this->post_id ) ); - // Ensure that the parentClientId points to a valid block. - $this->assertArrayHasKey( $block['parentClientId'], $parent_map ); - } - } + // Resolve blocks as nested. + $resolved_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); - // Now compare nested and flat structures. - $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); + $this->assertCount( 1, $resolved_blocks, 'There should be only one top-level block (columns).' ); + $this->assertEquals( 'core/columns', $resolved_blocks[0]['blockName'] ); + $this->assertNotEmpty( $resolved_blocks[0]['clientId'], 'The clientId should be set.' ); + $this->assertArrayNotHasKey( 'parentClientId', $resolved_blocks[0], 'The parentClientId should be empty.' ); - // Resolve blocks in nested mode. - $nested_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => false ] ); - // Resolve blocks in flat mode. - $flat_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); + $this->assertCount( 2, $resolved_blocks[0]['innerBlocks'], 'There should be two inner blocks (columns).' ); - // Convert nested blocks to flat structure for comparison. - $transformed_nested_blocks = $this->transformNestedToFlat( $nested_blocks ); + // Check the inner blocks. + $expected_parent_client_id = $resolved_blocks[0]['clientId']; - // Normalize both block arrays for comparison. - $normalized_nested_blocks = $this->normalizeBlocks( $transformed_nested_blocks ); - $normalized_flat_blocks = $this->normalizeBlocks( $flat_blocks ); + foreach ( $resolved_blocks[0]['innerBlocks'] as $inner_block ) { + $this->assertEquals( 'core/column', $inner_block['blockName'] ); + $this->assertCount( 2, $inner_block['innerBlocks'], 'There should be two inner blocks (column).' ); + $this->assertNotEmpty( $inner_block['clientId'], 'The clientId should be set.' ); + $this->assertArrayNotHasKey( 'parentClientId', $resolved_blocks[0], 'The parentClientId should only be set when flattening.' ); // @todo This is incorrect, the parentClientId should be set for nested blocks. - // Assert that the normalized structures match. - $this->assertEquals( $normalized_nested_blocks, $normalized_flat_blocks ); - } - - /** - * Helper function to transform nested blocks to flat structure. - */ - protected function transformNestedToFlat( array $nested_blocks ) { - $flat_blocks = []; + // Check the inner inner blocks. + $expected_parent_client_id = $inner_block['clientId']; - foreach ( $nested_blocks as $block ) { - $flat_blocks[] = $block; - if ( ! empty( $block['innerBlocks'] ) ) { - $flat_blocks = array_merge( $flat_blocks, $this->transformNestedToFlat( $block['innerBlocks'] ) ); + foreach ( $inner_block['innerBlocks'] as $inner_inner_block ) { + $this->assertNotEmpty( $inner_inner_block['clientId'], 'The clientId should be set.' ); + $this->assertArrayNotHasKey( 'parentClientId', $resolved_blocks[0], 'The parentClientId should only be set when flattening.' ); // @todo This is incorrect, the parentClientId should be set for nested blocks. } } - return $flat_blocks; + // Resolve blocks as flat. + $expected_parent_client_id = null; + $expected_blocks = $resolved_blocks; + + $resolved_blocks = $this->instance->resolve_content_blocks( $post, [ 'flat' => true ] ); + + $this->assertCount( 7, $resolved_blocks, 'There should be five blocks when flattened.' ); + + // Check the top-level block (columns). + $this->assertNotEmpty( $resolved_blocks[0]['clientId'], 'The clientId should be set.' ); + $this->assertEqualBlocks( $expected_blocks[0], $resolved_blocks[0], 'The top-level block should match.' ); + + // Check first inner block (column). + $expected_parent_client_id = $resolved_blocks[0]['clientId']; + $this->assertNotEmpty( $resolved_blocks[1]['clientId'], 'The clientId should be set.' ); + $this->assertEquals( $expected_parent_client_id, $resolved_blocks[1]['parentClientId'], 'The parentClientId should match.' ); + $this->assertEqualBlocks( $expected_blocks[0]['innerBlocks'][0], $resolved_blocks[1], 'The first inner block should match.' ); + + // Check first inner block children. + $expected_parent_client_id = $resolved_blocks[1]['clientId']; + $this->assertNotEmpty( $resolved_blocks[2]['clientId'], 'The clientId should be set.' ); + $this->assertEquals( $expected_parent_client_id, $resolved_blocks[2]['parentClientId'], 'The parentClientId should match.' ); + $this->assertEqualBlocks( $expected_blocks[0]['innerBlocks'][0]['innerBlocks'][0], $resolved_blocks[2], 'The first inner inner block should match.' ); + + $this->assertNotEmpty( $resolved_blocks[3]['clientId'], 'The clientId should be set.' ); + $this->assertEquals( $expected_parent_client_id, $resolved_blocks[3]['parentClientId'], 'The parentClientId should match.' ); + $this->assertEqualBlocks( $expected_blocks[0]['innerBlocks'][0]['innerBlocks'][1], $resolved_blocks[3], 'The second inner inner block should match.' ); + + // Check second inner block (column). + $expected_parent_client_id = $resolved_blocks[0]['clientId']; + $this->assertNotEmpty( $resolved_blocks[4]['clientId'], 'The clientId should be set.' ); + $this->assertEquals( $expected_parent_client_id, $resolved_blocks[4]['parentClientId'], 'The parentClientId should match.' ); + $this->assertEqualBlocks( $expected_blocks[0]['innerBlocks'][1], $resolved_blocks[4], 'The first inner block should match.' ); + + // Check second inner block children. + $expected_parent_client_id = $resolved_blocks[4]['clientId']; + $this->assertNotEmpty( $resolved_blocks[5]['clientId'], 'The clientId should be set.' ); + $this->assertEquals( $expected_parent_client_id, $resolved_blocks[5]['parentClientId'], 'The parentClientId should match.' ); + $this->assertEqualBlocks( $expected_blocks[0]['innerBlocks'][1]['innerBlocks'][0], $resolved_blocks[5], 'The first inner inner block should match.' ); + + $this->assertNotEmpty( $resolved_blocks[6]['clientId'], 'The clientId should be set.' ); + $this->assertEquals( $expected_parent_client_id, $resolved_blocks[6]['parentClientId'], 'The parentClientId should match.' ); + $this->assertEqualBlocks( $expected_blocks[0]['innerBlocks'][1]['innerBlocks'][1], $resolved_blocks[6], 'The second inner inner block should match.' ); } /** - * Helper function to normalize block structures for comparison. + * Asserts two blocks are equal, ignoring clientId and parentClientId. + * + * @param array $expected The expected block. + * @param array $actual The actual block. + * @param string $message The message to display if the assertion fails. */ - protected function normalizeBlocks( array $blocks ) { - return array_map( - function ( $block ) { + protected function assertEqualBlocks( $expected, $actual, $message = '' ) { + // Remove clientId and parentClientId from comparison. + unset( $expected['clientId'] ); + unset( $expected['parentClientId'] ); + unset( $actual['clientId'] ); + unset( $actual['parentClientId'] ); - // Remove 'clientId' and 'parentClientId' from comparison. - unset( $block['clientId'] ); - unset( $block['parentClientId'] ); + $expected_inner_blocks = $expected['innerBlocks'] ?? []; + $actual_inner_blocks = $actual['innerBlocks'] ?? []; - if ( ! empty( $block['innerBlocks'] ) ) { - $block['innerBlocks'] = $this->normalizeBlocks( $block['innerBlocks'] ); - } + unset( $expected['innerBlocks'] ); + unset( $actual['innerBlocks'] ); - return $block; - }, - $blocks - ); + $this->assertEquals( $expected, $actual, $message ); + + foreach ( $expected_inner_blocks as $index => $expected_inner_block ) { + $this->assertEqualBlocks( $expected_inner_block, $actual_inner_blocks[ $index ], $message ); + } } } From a38e4794bf235a34356760fab633d1ba3e94dd2c Mon Sep 17 00:00:00 2001 From: Ta5r Date: Mon, 23 Sep 2024 14:47:19 +0530 Subject: [PATCH 9/9] changeset : backfill tests for Content block Resolver --- .changeset/weak-days-suffer.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/weak-days-suffer.md diff --git a/.changeset/weak-days-suffer.md b/.changeset/weak-days-suffer.md new file mode 100644 index 00000000..a6297612 --- /dev/null +++ b/.changeset/weak-days-suffer.md @@ -0,0 +1,5 @@ +--- +"@wpengine/wp-graphql-content-blocks": patch +--- + +tests : backfill tests for ContentBlockResolver