Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Fix: skewed placeholder of product image - issue#7553 #7651

Merged
merged 13 commits into from
Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions assets/js/atomic/blocks/product-elements/image/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,7 @@ export const Block = ( props ) => {
};

const ImagePlaceholder = () => {
return (
<img src={ PLACEHOLDER_IMG_SRC } alt="" width={ 500 } height={ 500 } />
);
return <img src={ PLACEHOLDER_IMG_SRC } alt="Generic placeholder" />;
};

const Image = ( { image, loaded, showFullSize, fallbackAlt } ) => {
Expand Down
55 changes: 46 additions & 9 deletions assets/js/atomic/blocks/product-elements/image/test/block.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jest.mock( '@woocommerce/base-hooks', () => ( {
} ) ),
} ) );

const placeholderImageAlt = 'Generic placeholder';

const productWithoutImages = {
name: 'Test product',
id: 1,
Expand Down Expand Up @@ -62,7 +64,10 @@ describe( 'Product Image Block', () => {
describe( 'with product link', () => {
test( 'should render an anchor with the product image', () => {
const component = render(
<ProductDataContextProvider product={ productWithImages }>
<ProductDataContextProvider
product={ productWithImages }
isLoading={ false }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify why isLoading is hardcoded to false in the context of this test, and why was it needed to be added as a fix for this issue? 🤔

Copy link
Contributor Author

@kmanijak kmanijak Nov 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clarify why isLoading is hardcoded to false in the context of this test

Sure! I added isLoading prop to each test, as I realised it's a required prop for ProductDataContextProvider and TypeScript checker complained about that.
And considering the tests are checking the behaviour of component with images loaded already, I checked the code and isLoading passed as false seems to set such condition. Also, there's no default value for isLoading, so before adding that to tests, it was implicitly falsy.
But I may be missing something, so I'm all ears if you see that may be troublesome! 👂

and why was it needed to be added as a fix for this issue? 🤔

TS fixes/improvements were added as an extra to this PR and are not required as a fix for issue. I gathered them in a separate commit, but maybe I should've added it as a separate PR to avoid confusion. Let me know the way forward 🙌
EDIT: Or add it to the PR description in "Changes" section. Will keep that in mind for future.

>
<Block showProductLink={ true } />
</ProductDataContextProvider>
);
Expand All @@ -79,28 +84,32 @@ describe( 'Product Image Block', () => {
);

const anchor = productImage.closest( 'a' );
expect( anchor.getAttribute( 'href' ) ).toBe(
expect( anchor?.getAttribute( 'href' ) ).toBe(
productWithImages.permalink
);
} );

test( 'should render an anchor with the placeholder image', () => {
const component = render(
<ProductDataContextProvider product={ productWithoutImages }>
<ProductDataContextProvider
product={ productWithoutImages }
isLoading={ false }
>
<Block showProductLink={ true } />
</ProductDataContextProvider>
);

const placeholderImage = component.getByAltText( '' );
const placeholderImage =
component.getByAltText( placeholderImageAlt );
expect( placeholderImage.getAttribute( 'src' ) ).toBe(
'placeholder.jpg'
);

const anchor = placeholderImage.closest( 'a' );
expect( anchor.getAttribute( 'href' ) ).toBe(
expect( anchor?.getAttribute( 'href' ) ).toBe(
productWithoutImages.permalink
);
expect( anchor.getAttribute( 'aria-label' ) ).toBe(
expect( anchor?.getAttribute( 'aria-label' ) ).toBe(
`Link to ${ productWithoutImages.name }`
);
} );
Expand All @@ -109,7 +118,10 @@ describe( 'Product Image Block', () => {
describe( 'without product link', () => {
test( 'should render the product image without an anchor wrapper', () => {
const component = render(
<ProductDataContextProvider product={ productWithImages }>
<ProductDataContextProvider
product={ productWithImages }
isLoading={ false }
>
<Block showProductLink={ false } />
</ProductDataContextProvider>
);
Expand All @@ -129,12 +141,16 @@ describe( 'Product Image Block', () => {

test( 'should render the placeholder image without an anchor wrapper', () => {
const component = render(
<ProductDataContextProvider product={ productWithoutImages }>
<ProductDataContextProvider
product={ productWithoutImages }
isLoading={ false }
>
<Block showProductLink={ false } />
</ProductDataContextProvider>
);

const placeholderImage = component.getByAltText( '' );
const placeholderImage =
component.getByAltText( placeholderImageAlt );
expect( placeholderImage.getAttribute( 'src' ) ).toBe(
'placeholder.jpg'
);
Expand All @@ -143,4 +159,25 @@ describe( 'Product Image Block', () => {
expect( anchor ).toBe( null );
} );
} );

describe( 'without image', () => {
test( 'should render the placeholder with no inline width or height attributes', () => {
const component = render(
<ProductDataContextProvider
product={ productWithoutImages }
isLoading={ false }
>
<Block showProductLink={ true } />
</ProductDataContextProvider>
);

const placeholderImage =
component.getByAltText( placeholderImageAlt );
expect( placeholderImage.getAttribute( 'src' ) ).toBe(
'placeholder.jpg'
);
expect( placeholderImage.getAttribute( 'width' ) ).toBe( null );
expect( placeholderImage.getAttribute( 'height' ) ).toBe( null );
} );
} );
} );
17 changes: 4 additions & 13 deletions checkstyle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1121,10 +1121,10 @@
<error line="75" column="36" severity="error" message="Property &apos;max_amount&apos; does not exist on type &apos;never&apos;." source="TS2339" />
</file>
<file name="assets/js/atomic/blocks/product-elements/image/block.js">
<error line="137" column="19" severity="error" message="Binding element &apos;image&apos; implicitly has an &apos;any&apos; type." source="TS7031" />
<error line="137" column="26" severity="error" message="Binding element &apos;loaded&apos; implicitly has an &apos;any&apos; type." source="TS7031" />
<error line="137" column="34" severity="error" message="Binding element &apos;showFullSize&apos; implicitly has an &apos;any&apos; type." source="TS7031" />
<error line="137" column="48" severity="error" message="Binding element &apos;fallbackAlt&apos; implicitly has an &apos;any&apos; type." source="TS7031" />
<error line="135" column="19" severity="error" message="Binding element &apos;image&apos; implicitly has an &apos;any&apos; type." source="TS7031" />
<error line="135" column="26" severity="error" message="Binding element &apos;loaded&apos; implicitly has an &apos;any&apos; type." source="TS7031" />
<error line="135" column="34" severity="error" message="Binding element &apos;showFullSize&apos; implicitly has an &apos;any&apos; type." source="TS7031" />
<error line="135" column="48" severity="error" message="Binding element &apos;fallbackAlt&apos; implicitly has an &apos;any&apos; type." source="TS7031" />
</file>
<file name="assets/js/atomic/blocks/product-elements/rating/block.tsx">
<error line="55" column="35" severity="error" message="Argument of type &apos;{ id: number; name: string; parent: number; type: string; variation: string; permalink: string; sku: string; short_description: string; description: string; on_sale: boolean; prices: { currency_code: string; ... 9 more ...; price_range: null; }; ... 14 more ...; add_to_cart: { ...; }; }&apos; is not assignable to parameter of type &apos;Omit&lt;ProductResponseItem, &quot;average_rating&quot;&gt; &amp; { average_rating: string; }&apos;.
Expand Down Expand Up @@ -1457,15 +1457,6 @@
<error line="252" column="56" severity="error" message="Argument of type &apos;null&apos; is not assignable to parameter of type &apos;Object&apos;." source="TS2345" />
<error line="475" column="34" severity="error" message="Argument of type &apos;null&apos; is not assignable to parameter of type &apos;Object | undefined&apos;." source="TS2345" />
</file>
<file name="assets/js/atomic/blocks/product-elements/image/test/block.test.js">
<error line="65" column="6" severity="error" message="Property &apos;isLoading&apos; is missing in type &apos;{ children: Element; product: { name: string; id: number; fallbackAlt: string; permalink: string; images: { id: number; src: string; thumbnail: string; srcset: string; sizes: string; name: string; alt: string; }[]; }; }&apos; but required in type &apos;{ product: any; children: Object; isLoading: boolean; }&apos;." source="TS2741" />
<error line="82" column="12" severity="error" message="Object is possibly &apos;null&apos;." source="TS2531" />
<error line="89" column="6" severity="error" message="Property &apos;isLoading&apos; is missing in type &apos;{ children: Element; product: { name: string; id: number; fallbackAlt: string; permalink: string; images: never[]; }; }&apos; but required in type &apos;{ product: any; children: Object; isLoading: boolean; }&apos;." source="TS2741" />
<error line="100" column="12" severity="error" message="Object is possibly &apos;null&apos;." source="TS2531" />
<error line="103" column="12" severity="error" message="Object is possibly &apos;null&apos;." source="TS2531" />
<error line="112" column="6" severity="error" message="Property &apos;isLoading&apos; is missing in type &apos;{ children: Element; product: { name: string; id: number; fallbackAlt: string; permalink: string; images: { id: number; src: string; thumbnail: string; srcset: string; sizes: string; name: string; alt: string; }[]; }; }&apos; but required in type &apos;{ product: any; children: Object; isLoading: boolean; }&apos;." source="TS2741" />
<error line="132" column="6" severity="error" message="Property &apos;isLoading&apos; is missing in type &apos;{ children: Element; product: { name: string; id: number; fallbackAlt: string; permalink: string; images: never[]; }; }&apos; but required in type &apos;{ product: any; children: Object; isLoading: boolean; }&apos;." source="TS2741" />
</file>
<file name="assets/js/atomic/blocks/product-elements/title/test/block.test.js">
<error line="22" column="6" severity="error" message="Property &apos;isLoading&apos; is missing in type &apos;{ children: Element; product: { id: number; name: string; permalink: string; }; }&apos; but required in type &apos;{ product: any; children: Object; isLoading: boolean; }&apos;." source="TS2741" />
<error line="23" column="7" severity="error" message="Type &apos;{ showProductLink: false; }&apos; is missing the following properties from type &apos;Attributes&apos;: headingLevel, align" source="TS2739" />
Expand Down
2 changes: 1 addition & 1 deletion src/BlockTypes/ProductImage.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ private function render_image( $product ) {
$image_info = wp_get_attachment_image_src( get_post_thumbnail_id( $product->get_id() ), 'woocommerce_thumbnail' );

if ( ! isset( $image_info[0] ) ) {
return sprintf( '<img src="%s" alt="" width="500 height="500" />', wc_placeholder_img_src( 'woocommerce_thumbnail' ) );
return sprintf( '<img src="%s" alt="" />', wc_placeholder_img_src( 'woocommerce_thumbnail' ) );
}

return sprintf(
Expand Down