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 ( ); }; 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