* Create the `Products by Attribute` template

* bot: update checkstyle.xml

* Fix typo

* Rename template to `taxonomy-product_attribute`

* Rename test template file

* bot: update checkstyle.xml

* Fix test enabling archives for shade attribute

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Alba Rincón 2022-11-16 14:37:41 +01:00 committed by GitHub
parent ddd0cc2300
commit 87510929b5
11 changed files with 149 additions and 13 deletions

View File

@ -18,7 +18,7 @@ This block does not have any customizable options available, so any style or cus
### Props
- `attributes`
- `template`: `single-product` | `archive-product` | `taxonomy-product_cat` | `taxonomy-product_tag`
- `template`: `single-product` | `archive-product` | `taxonomy-product_cat` | `taxonomy-product_tag` | `taxonomy-product_attribute`
- `align`: `wide` | `full`
```html

View File

@ -38,6 +38,13 @@ export const TEMPLATES: TemplateDetails = {
),
placeholder: 'archive-product',
},
'taxonomy-product_attribute': {
title: __(
'WooCommerce Product Attribute Block',
'woo-gutenberg-products-block'
),
placeholder: 'archive-product',
},
'product-search-results': {
title: __(
'WooCommerce Product Search Results Block',

View File

@ -20,6 +20,10 @@ const TEMPLATES = {
title: 'Product Taxonomy Title',
placeholder: 'Product Taxonomy Placeholder',
},
'taxonomy-product_attribute': {
title: 'Product Attribute Title',
placeholder: 'Product Attribute Placeholder',
},
};
describe( 'getTemplateDetailsBySlug', function () {

View File

@ -2,6 +2,7 @@
namespace Automattic\WooCommerce\Blocks;
use Automattic\WooCommerce\Blocks\Domain\Package;
use Automattic\WooCommerce\Blocks\Templates\ProductAttributeTemplate;
use Automattic\WooCommerce\Blocks\Utils\BlockTemplateUtils;
/**
@ -110,7 +111,7 @@ class BlockTemplatesController {
list( $template_id, $template_slug ) = $template_name_parts;
// If the theme has an archive-product.html template, but not a taxonomy-product_cat/tag.html template let's use the themes archive-product.html template.
// If the theme has an archive-product.html template, but not a taxonomy-product_cat/tag/attribute.html template let's use the themes archive-product.html template.
if ( BlockTemplateUtils::template_is_eligible_for_product_archive_fallback( $template_slug ) ) {
$template_path = BlockTemplateUtils::get_theme_template_path( 'archive-product' );
$template_object = BlockTemplateUtils::create_new_block_template_object( $template_path, $template_type, $template_slug, true );
@ -330,7 +331,7 @@ class BlockTemplatesController {
continue;
}
// If the theme has an archive-product.html template, but not a taxonomy-product_cat.html template let's use the themes archive-product.html template.
// If the theme has an archive-product.html template, but not a taxonomy-product_cat/tag/attribute.html template let's use the themes archive-product.html template.
if ( BlockTemplateUtils::template_is_eligible_for_product_archive_fallback( $template_slug ) ) {
$template_file = BlockTemplateUtils::get_theme_template_path( 'archive-product' );
$templates[] = BlockTemplateUtils::create_new_block_template_object( $template_file, $template_type, $template_slug, true );
@ -439,8 +440,8 @@ class BlockTemplatesController {
}
if ( isset( $queried_object->taxonomy ) && taxonomy_is_product_attribute( $queried_object->taxonomy ) &&
! BlockTemplateUtils::theme_has_template( 'archive-product' ) &&
$this->block_template_is_available( 'archive-product' )
! BlockTemplateUtils::theme_has_template( ProductAttributeTemplate::SLUG ) &&
$this->block_template_is_available( ProductAttributeTemplate::SLUG )
) {
add_filter( 'woocommerce_has_block_template', '__return_true', 10, 0 );
}

View File

@ -1,6 +1,7 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;
use Automattic\WooCommerce\Blocks\Templates\ProductAttributeTemplate;
use Automattic\WooCommerce\Blocks\Templates\ProductSearchResultsTemplate;
use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
use WC_Query;
@ -61,7 +62,7 @@ class ClassicTemplate extends AbstractDynamicBlock {
$frontend_scripts::load_scripts();
}
$archive_templates = array( 'archive-product', 'taxonomy-product_cat', 'taxonomy-product_tag', ProductSearchResultsTemplate::SLUG );
$archive_templates = array( 'archive-product', 'taxonomy-product_cat', 'taxonomy-product_tag', ProductAttributeTemplate::SLUG, ProductSearchResultsTemplate::SLUG );
if ( 'single-product' === $attributes['template'] ) {
return $this->render_single_product();

View File

@ -8,7 +8,7 @@ namespace Automattic\WooCommerce\Blocks\Templates;
* @internal
*/
class ProductAttributeTemplate {
const SLUG = 'archive-product';
const SLUG = 'taxonomy-product_attribute';
/**
* Constructor.
@ -25,14 +25,14 @@ class ProductAttributeTemplate {
}
/**
* Render the Archive Product Template for product attributes.
* Renders the Product by Attribute template for product attributes taxonomy pages.
*
* @param array $templates Templates that match the product attributes taxonomy.
*/
public function update_taxonomy_template_hierarchy( $templates ) {
$queried_object = get_queried_object();
if ( taxonomy_is_product_attribute( $queried_object->taxonomy ) && wc_current_theme_is_fse_theme() ) {
array_unshift( $templates, self::SLUG );
array_splice( $templates, count( $templates ) - 1, 0, self::SLUG );
}
return $templates;

View File

@ -1,6 +1,7 @@
<?php
namespace Automattic\WooCommerce\Blocks\Utils;
use Automattic\WooCommerce\Blocks\Templates\ProductAttributeTemplate;
use Automattic\WooCommerce\Blocks\Templates\ProductSearchResultsTemplate;
use Automattic\WooCommerce\Blocks\Domain\Services\FeatureGating;
use Automattic\WooCommerce\Blocks\Options;
@ -312,6 +313,10 @@ class BlockTemplateUtils {
'title' => _x( 'Products by Tag', 'Template name', 'woo-gutenberg-products-block' ),
'description' => __( 'Displays products filtered by a tag.', 'woo-gutenberg-products-block' ),
),
ProductAttributeTemplate::SLUG => array(
'title' => _x( 'Products by Attribute', 'Template name', 'woo-gutenberg-products-block' ),
'description' => __( 'Displays products filtered by an attribute.', 'woo-gutenberg-products-block' ),
),
ProductSearchResultsTemplate::SLUG => array(
'title' => _x( 'Product Search Results', 'Template name', 'woo-gutenberg-products-block' ),
'description' => __( 'Displays search results for your store.', 'woo-gutenberg-products-block' ),
@ -449,14 +454,14 @@ class BlockTemplateUtils {
/**
* Checks if we can fallback to the `archive-product` template for a given slug
*
* `taxonomy-product_cat` and `taxonomy-product_tag` templates can generally use the
* `archive-product` as a fallback if there are no specific overrides.
* `taxonomy-product_cat`, `taxonomy-product_tag`, `taxonomy-attribute` templates can
* generally use the `archive-product` as a fallback if there are no specific overrides.
*
* @param string $template_slug Slug to check for fallbacks.
* @return boolean
*/
public static function template_is_eligible_for_product_archive_fallback( $template_slug ) {
$eligible_for_fallbacks = array( 'taxonomy-product_cat', 'taxonomy-product_tag' );
$eligible_for_fallbacks = array( 'taxonomy-product_cat', 'taxonomy-product_tag', ProductAttributeTemplate::SLUG );
return in_array( $template_slug, $eligible_for_fallbacks, true )
&& ! self::theme_has_template( $template_slug )

View File

@ -0,0 +1,5 @@
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<!-- wp:group {"layout":{"inherit":true}} -->
<div class="wp-block-group"><!-- wp:woocommerce/legacy-template {"template":"taxonomy-product_attribute"} /--></div>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->

View File

@ -26,7 +26,10 @@ const Attributes = () => [
],
},
{
attribute: { name: 'Shade' },
attribute: {
name: 'Shade',
has_archives: true,
},
terms: [
{
name: 'Red',

View File

@ -93,6 +93,14 @@ const BLOCK_DATA = {
},
name: 'woocommerce/legacy-template',
},
'taxonomy-product_attribute': {
attributes: {
placeholder: 'archive-product',
template: 'taxonomy-product_attribute',
title: 'WooCommerce Product Attribute Block',
},
name: 'woocommerce/legacy-template',
},
'product-search-results': {
attributes: {
title: 'WooCommerce Product Search Results Block',
@ -516,6 +524,100 @@ describe( 'Store Editing Templates', () => {
} );
} );
describe( 'Products by Attribute template', () => {
it( 'default template from WooCommerce Blocks is available on an FSE theme', async () => {
const EXPECTED_TEMPLATE = defaultTemplateProps(
'Products by Attribute'
);
await goToTemplatesList();
const templates = await getAllTemplates();
try {
expect( templates ).toContainEqual( EXPECTED_TEMPLATE );
} catch ( ok ) {
// Depending on the speed of the execution and whether Chrome is headless or not
// the id might be parsed or not
expect( templates ).toContainEqual( {
...EXPECTED_TEMPLATE,
addedBy: WOOCOMMERCE_PARSED_ID,
} );
}
} );
runOnlyWhenGutenbergIsDisabled( () =>
it( 'should contain the "WooCommerce Product Taxonomy Block" classic template', async () => {
await goToTemplateEditor( {
postId: 'woocommerce/woocommerce//taxonomy-product_attribute',
} );
const [ classicBlock ] = await filterCurrentBlocks(
( block ) =>
block.name ===
BLOCK_DATA[ 'taxonomy-product_attribute' ].name
);
expect( classicBlock.attributes.template ).toBe(
BLOCK_DATA[ 'taxonomy-product_attribute' ].attributes
.template
);
expect( await getCurrentSiteEditorContent() ).toMatchSnapshot();
} )
);
it( 'should show the action menu if the template has been customized by the user', async () => {
const EXPECTED_TEMPLATE = {
...defaultTemplateProps( 'Products by Attribute' ),
hasActions: true,
};
await visitTemplateAndAddCustomParagraph(
'taxonomy-product_attribute'
);
await goToTemplatesList( { waitFor: 'actions' } );
const templates = await getAllTemplates();
try {
expect( templates ).toContainEqual( EXPECTED_TEMPLATE );
} catch ( ok ) {
// Depending on the speed of the execution and whether Chrome is headless or not
// the id might be parsed or not
expect( templates ).toContainEqual( {
...EXPECTED_TEMPLATE,
addedBy: WOOCOMMERCE_PARSED_ID,
} );
}
} );
it( 'should preserve and correctly show the user customization on the back-end', async () => {
await goToTemplateEditor( {
postId: 'woocommerce/woocommerce//taxonomy-product_attribute',
} );
await expect( canvas() ).toMatchElement(
SELECTORS.blocks.paragraph,
{
text: CUSTOMIZED_STRING,
timeout: DEFAULT_TIMEOUT,
}
);
} );
it( 'should show the user customization on the front-end', async () => {
await page.goto( new URL( '/shade/red', BASE_URL ) );
await expect( page ).toMatchElement( 'p', {
text: CUSTOMIZED_STRING,
timeout: DEFAULT_TIMEOUT,
} );
} );
} );
describe( 'Product Search Results block template', () => {
it( 'default template from WooCommerce Blocks is available on an FSE theme', async () => {
const EXPECTED_TEMPLATE = defaultTemplateProps(

View File

@ -0,0 +1,8 @@
<!-- wp:template-part {"slug":"header"} /-->
<!-- wp:group {"layout":{"inherit":true}} -->
<h2 class="theme-template-title">Template loaded from theme</h2>
<div class="wp-block-group">
<!-- wp:woocommerce/legacy-template {"template":"taxonomy-product_attribute"} /-->
</div>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer"} /-->