From 84f2de633d25373fcb8b3f1035a3b8c19071d256 Mon Sep 17 00:00:00 2001
From: Karol Manijak <20098064+kmanijak@users.noreply.github.com>
Date: Thu, 1 Feb 2024 17:55:38 +0100
Subject: [PATCH] Fix incorrect product data displayed in Product Collection in
context of Single Product block (#44123)
* Initial approach to fix incorrect product data displayed in Product Collection in context of Single Product block
* Remove the BlockCOntextProvider
* Add Block context for title and summary
* Add changelog
* Improve typing
* Add E2E test with Product Collection inside Single Product block
* Improve insertBLock function description
* Make productPrices selector in Product Collectionmore specific
* Extract components props into a types
---
.../js/blocks/product-template/edit.tsx | 103 +++++++++++++-----
.../product-collection.block_theme.spec.ts | 67 ++++++++++++
.../product-collection.page.ts | 2 +-
.../e2e/utils/editor/editor-utils.page.ts | 2 +-
...ct-block-when-used-in-single-product-block | 4 +
5 files changed, 148 insertions(+), 30 deletions(-)
create mode 100644 plugins/woocommerce/changelog/43991-product-collection-displays-content-from-single-product-block-when-used-in-single-product-block
diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-template/edit.tsx b/plugins/woocommerce-blocks/assets/js/blocks/product-template/edit.tsx
index 403210261e8..470a96253db 100644
--- a/plugins/woocommerce-blocks/assets/js/blocks/product-template/edit.tsx
+++ b/plugins/woocommerce-blocks/assets/js/blocks/product-template/edit.tsx
@@ -15,10 +15,12 @@ import {
} from '@wordpress/block-editor';
import { Spinner } from '@wordpress/components';
import { store as coreStore } from '@wordpress/core-data';
-import type { BlockEditProps } from '@wordpress/blocks';
import { ProductCollectionAttributes } from '@woocommerce/blocks/product-collection/types';
import { getSettingWithCoercion } from '@woocommerce/settings';
-import { isNumber } from '@woocommerce/types';
+import { isNumber, ProductResponseItem } from '@woocommerce/types';
+import { ProductDataContextProvider } from '@woocommerce/shared-context';
+import { withProduct } from '@woocommerce/block-hocs';
+import type { BlockEditProps, BlockInstance } from '@wordpress/blocks';
const ProductTemplateInnerBlocks = () => {
const innerBlocksProps = useInnerBlocksProps(
@@ -28,17 +30,19 @@ const ProductTemplateInnerBlocks = () => {
return
;
};
+type ProductTemplateBlockPreviewProps = {
+ blocks: object[];
+ blockContextId: string;
+ isHidden: boolean;
+ setActiveBlockContextId: ( blockContextId: string ) => void;
+};
+
const ProductTemplateBlockPreview = ( {
blocks,
blockContextId,
isHidden,
setActiveBlockContextId,
-}: {
- blocks: object[];
- blockContextId: string;
- isHidden: boolean;
- setActiveBlockContextId: ( blockContextId: string ) => void;
-} ) => {
+}: ProductTemplateBlockPreviewProps ) => {
const blockPreviewProps = useBlockPreview( {
blocks,
props: {
@@ -69,6 +73,50 @@ const ProductTemplateBlockPreview = ( {
const MemoizedProductTemplateBlockPreview = memo( ProductTemplateBlockPreview );
+type ProductContentProps = {
+ attributes: { productId: string };
+ isLoading: boolean;
+ product: ProductResponseItem;
+ displayTemplate: boolean;
+ blocks: BlockInstance[];
+ blockContext: {
+ postType: string;
+ postId: string;
+ };
+ setActiveBlockContextId: ( id: string ) => void;
+};
+
+const ProductContent = withProduct(
+ ( {
+ isLoading,
+ product,
+ displayTemplate,
+ blocks,
+ blockContext,
+ setActiveBlockContextId,
+ }: ProductContentProps ) => {
+ return (
+
+
+ { displayTemplate ? : null }
+
+
+
+ );
+ }
+);
+
const ProductTemplateEdit = ( {
clientId,
context: {
@@ -100,7 +148,8 @@ const ProductTemplateEdit = ( {
__unstableLayoutClassNames: string;
} ) => {
const [ { page } ] = queryContext;
- const [ activeBlockContextId, setActiveBlockContextId ] = useState();
+ const [ activeBlockContextId, setActiveBlockContextId ] =
+ useState< string >();
const postType = 'product';
const loopShopPerPage = getSettingWithCoercion(
'loopShopPerPage',
@@ -241,28 +290,26 @@ const ProductTemplateEdit = ( {
return (
{ blockContexts &&
- blockContexts.map( ( blockContext ) => (
-
- { blockContext.postId ===
- ( activeBlockContextId ||
- blockContexts[ 0 ]?.postId ) ? (
-
- ) : null }
- {
+ const displayTemplate =
+ blockContext.postId ===
+ ( activeBlockContextId || blockContexts[ 0 ]?.postId );
+
+ return (
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore isLoading and product props are missing as they're coming from untyped withProduct HOC.
+
-
- ) ) }
+ );
+ } ) }
);
};
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.block_theme.spec.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.block_theme.spec.ts
index 794ed04969f..d7104a13696 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.block_theme.spec.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.block_theme.spec.ts
@@ -674,4 +674,71 @@ test.describe( 'Product Collection', () => {
} );
} );
} );
+
+ test.describe( 'With other blocks', () => {
+ test( 'In Single Product block', async ( {
+ admin,
+ editor,
+ page,
+ editorUtils,
+ pageObject,
+ } ) => {
+ await admin.createNewPost();
+ await editorUtils.closeWelcomeGuideModal();
+
+ // Prepare Single Product block
+ await editor.insertBlock( { name: 'woocommerce/single-product' } );
+ await page.waitForResponse(
+ ( response ) =>
+ response.url().includes( 'wc/store/v1/products' ) &&
+ response.status() === 200
+ );
+ const singleProductBlock = await editorUtils.getBlockByName(
+ 'woocommerce/single-product'
+ );
+ await singleProductBlock
+ .locator( 'input[type="radio"]' )
+ .nth( 0 )
+ .click();
+ await singleProductBlock.getByText( 'Done' ).click();
+
+ await page.getByLabel( 'Block: Product Title' ).press( 'Enter' );
+ await page
+ .getByLabel(
+ 'Empty block; start writing or type forward slash to choose a block'
+ )
+ .pressSequentially( '/Product Collection (Beta)' );
+ await page
+ .getByRole( 'option', {
+ name: 'Product Collection (Beta)',
+ exact: true,
+ } )
+ .first()
+ .click();
+ await pageObject.chooseCollectionInPost( 'featured' );
+
+ const featuredProducts = [
+ 'Cap',
+ 'Hoodie with Zipper',
+ 'Sunglasses',
+ 'V-Neck T-Shirt',
+ ];
+ const featuredProductsPrices = [
+ 'Previous price:$18.00Discounted price:$16.00',
+ '$45.00',
+ '$90.00',
+ 'Price between $15.00 and $20.00$15.00 — $20.00',
+ ];
+
+ await expect( pageObject.products ).toHaveCount( 4 );
+ // This verifies if Core's block context is provided
+ await expect( pageObject.productTitles ).toHaveText(
+ featuredProducts
+ );
+ // This verifies if Blocks's product context is provided
+ await expect( pageObject.productPrices ).toHaveText(
+ featuredProductsPrices
+ );
+ } );
+ } );
} );
diff --git a/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.page.ts b/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.page.ts
index ef944d949e2..22ed71258f7 100644
--- a/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.page.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/tests/product-collection/product-collection.page.ts
@@ -526,7 +526,7 @@ class ProductCollectionPage {
this.productTitles = this.productTemplate
.locator( SELECTORS.productTitle )
.locator( 'visible=true' );
- this.productPrices = this.page
+ this.productPrices = this.productTemplate
.locator( SELECTORS.productPrice.inEditor )
.locator( 'visible=true' );
this.addToCartButtons = this.page
diff --git a/plugins/woocommerce-blocks/tests/e2e/utils/editor/editor-utils.page.ts b/plugins/woocommerce-blocks/tests/e2e/utils/editor/editor-utils.page.ts
index f7d34c90334..75e1eaffa1f 100644
--- a/plugins/woocommerce-blocks/tests/e2e/utils/editor/editor-utils.page.ts
+++ b/plugins/woocommerce-blocks/tests/e2e/utils/editor/editor-utils.page.ts
@@ -47,7 +47,7 @@ export class EditorUtils {
// todo: Make a PR to @wordpress/e2e-test-utils-playwright to add this method.
/**
- * Inserts a block after a given client ID.
+ * Inserts a block inside a given client ID.
*
*/
async insertBlock(
diff --git a/plugins/woocommerce/changelog/43991-product-collection-displays-content-from-single-product-block-when-used-in-single-product-block b/plugins/woocommerce/changelog/43991-product-collection-displays-content-from-single-product-block-when-used-in-single-product-block
new file mode 100644
index 00000000000..d041177ce32
--- /dev/null
+++ b/plugins/woocommerce/changelog/43991-product-collection-displays-content-from-single-product-block-when-used-in-single-product-block
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Product Collection: fix incorrect product data being displayed when Product Collection is placed in Single Product block