Stop hidden products from being linked in cart and checkout blocks (https://github.com/woocommerce/woocommerce-blocks/pull/3415)

* Add catalog_visibility to CartItemSchema.php

This is used to get whether the product is visible in the catalogue, visible in the shop only, visible in search results only, or visible everywhere. We need to know this so we can pass it to the ProductImage and ProductName components.

* Remove links from CartLineItemRow if not visible in catalogue

Added catalog_visibility to lineItems prop, and when the product is not visible in the catalogue do not wrap product image in a link. Also pass down the hasLink prop to ProductName.

* Add hasLink prop to ProductName

When this prop is false we should not output the link around the product name. This is for when the product is hidden from the catalogue but we still want to show its name somewhere.

* Add tests and storybook for ProductName

* Add catalog_visibility check to OrderSummaryItem

When the catalogue visibility of a product is set to hidden or search, then the product name in the checkout sidebar should not be hyperlinked.

* Reverse logic for hiding link on product image & disabling link on name

Following a point from @budzanowski we do not need the hasLink prop, making use of disabled is probably a better idea.

* Remove tabindex from a in ProductName & output span if name is disabled

This change removes the need to pass a tabindex to the a in ProductName. This is because a disabled ProductName will now never output an a tag. When the ProductName is disabled a span is output instead, which has no tabindex by default.

This change also reverses the logic to decide whether the a or span should be output so as to make the code more readable and flow better.

* Update storybook and tests/snapshots for ProductName
This commit is contained in:
opr 2020-11-23 13:03:08 +00:00 committed by GitHub
parent f6c8d91b9d
commit fcfe5ee7dc
8 changed files with 118 additions and 12 deletions

View File

@ -18,6 +18,7 @@ import Dinero from 'dinero.js';
const OrderSummaryItem = ( { cartItem } ) => {
const {
images,
catalog_visibility: catalogVisibility = '',
low_stock_remaining: lowStockRemaining = null,
show_backorder_badge: showBackorderBadge = false,
name,
@ -37,6 +38,8 @@ const OrderSummaryItem = ( { cartItem } ) => {
.multiply( quantity )
.convertPrecision( currency.minorUnit )
.getAmount();
const shouldLinkToProduct =
catalogVisibility !== 'hidden' && catalogVisibility !== 'search';
return (
<div className="wc-block-components-order-summary-item">
@ -55,7 +58,11 @@ const OrderSummaryItem = ( { cartItem } ) => {
</div>
<div className="wc-block-components-order-summary-item__description">
<div className="wc-block-components-order-summary-item__header">
<ProductName permalink={ permalink } name={ name } />
<ProductName
hasLink={ shouldLinkToProduct }
permalink={ permalink }
name={ name }
/>
<ProductPrice
currency={ currency }
price={ linePrice }

View File

@ -10,14 +10,12 @@ import { decodeEntities } from '@wordpress/html-entities';
import './style.scss';
const ProductName = ( { name, permalink, disabled = false } ) => {
return (
// we use tabIndex -1 to prevent the link from being focused, pointer-events
// disabled click events, so we get an almost disabled link.
<a
className="wc-block-components-product-name"
href={ permalink }
tabIndex={ disabled ? -1 : 0 }
>
return disabled ? (
<span className="wc-block-components-product-name">
{ decodeEntities( name ) }
</span>
) : (
<a className="wc-block-components-product-name" href={ permalink }>
{ decodeEntities( name ) }
</a>
);

View File

@ -0,0 +1,26 @@
/**
* External dependencies
*/
import { boolean } from '@storybook/addon-knobs';
/**
* Internal dependencies
*/
import ProductName from '../';
export default {
title: 'WooCommerce Blocks/@base-components/cart-checkout/ProductName',
component: ProductName,
};
export const Default = () => {
const disabled = boolean( 'disabled', false );
return (
<ProductName
disabled={ disabled }
name={ 'Test product' }
permalink={ '/' }
/>
);
};

View File

@ -0,0 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ProductName should not render a link if disabled is true 1`] = `
<span
className="wc-block-components-product-name"
>
Test product
</span>
`;
exports[`ProductName should render a link if disabled is false 1`] = `
<a
className="wc-block-components-product-name"
>
Test product
</a>
`;
exports[`ProductName should render a link if disabled is not defined 1`] = `
<a
className="wc-block-components-product-name"
>
Test product
</a>
`;

View File

@ -0,0 +1,35 @@
/**
* External dependencies
*/
import TestRenderer from 'react-test-renderer';
/**
* Internal dependencies
*/
import ProductName from '..';
describe( 'ProductName', () => {
test( 'should not render a link if disabled is true', () => {
const component = TestRenderer.create(
<ProductName disabled={ true } name={ 'Test product' } />
);
expect( component.toJSON() ).toMatchSnapshot();
} );
test( 'should render a link if disabled is false', () => {
const component = TestRenderer.create(
<ProductName disabled={ false } name={ 'Test product' } />
);
expect( component.toJSON() ).toMatchSnapshot();
} );
test( 'should render a link if disabled is not defined', () => {
const component = TestRenderer.create(
<ProductName name={ 'Test product' } />
);
expect( component.toJSON() ).toMatchSnapshot();
} );
} );

View File

@ -43,6 +43,7 @@ const getAmountFromRawPrice = ( priceObject, currency ) => {
const CartLineItemRow = ( { lineItem = {} } ) => {
const {
name = '',
catalog_visibility: catalogVisibility = '',
short_description: shortDescription = '',
description: fullDescription = '',
low_stock_remaining: lowStockRemaining = null,
@ -90,6 +91,8 @@ const CartLineItemRow = ( { lineItem = {} } ) => {
} ).multiply( quantity );
const saleAmount = regularAmount.subtract( purchaseAmount );
const firstImage = images.length ? images[ 0 ] : {};
const isProductHiddenFromCatalog =
catalogVisibility === 'hidden' || catalogVisibility === 'search';
return (
<tr
@ -103,15 +106,19 @@ const CartLineItemRow = ( { lineItem = {} } ) => {
aria-hidden={ ! firstImage.alt }
>
{ /* We don't need to make it focusable, because product name has the same link. */ }
<a href={ permalink } tabIndex={ -1 }>
{ isProductHiddenFromCatalog ? (
<ProductImage image={ firstImage } />
</a>
) : (
<a href={ permalink } tabIndex={ -1 }>
<ProductImage image={ firstImage } />
</a>
) }
</td>
<td className="wc-block-cart-item__product">
<ProductName
permalink={ permalink }
name={ name }
disabled={ isPendingDelete }
disabled={ isPendingDelete || isProductHiddenFromCatalog }
/>
{ showBackorderBadge ? (
<ProductBackorderBadge />

View File

@ -260,6 +260,12 @@ class CartItemSchema extends ProductSchema {
]
),
],
'catalog_visibility' => [
'description' => __( 'Whether the product is visible in the catalog', 'woo-gutenberg-products-block' ),
'type' => 'string',
'context' => [ 'view', 'edit' ],
'readonly' => true,
],
self::EXTENDING_KEY => $this->get_extended_schema( self::IDENTIFIER ),
];
}
@ -299,6 +305,7 @@ class CartItemSchema extends ProductSchema {
'line_total_tax' => $this->prepare_money_response( $cart_item['line_tax'], wc_get_price_decimals() ),
]
),
'catalog_visibility' => $product->get_catalog_visibility(),
self::EXTENDING_KEY => $this->get_extended_data( self::IDENTIFIER, $cart_item ),
];
}

View File

@ -245,6 +245,7 @@ class CartItems extends TestCase {
$this->assertArrayHasKey( 'backorders_allowed', $data );
$this->assertArrayHasKey( 'show_backorder_badge', $data );
$this->assertArrayHasKey( 'short_description', $data );
$this->assertArrayHasKey( 'catalog_visibility', $data );
}
/**