Prevent collection different than Product Catalog from being filtered (#45820)

* Prevent collection different than Produyct Catalog from being filtered

* Adjust Product Filters tests

* Split taxonomies filter into seperate filter per taxonomy

* Add changelog

* Improve onDeselect function

* Update Product Filter test handlebars so they all use Product Collection that inherits query from template

* Set Product Collection to inherit query from template in PHP unit tests

* Remove unnecessary empty space

* Add changelog

* Update tests

* Fix lint

* Update Product Collection attributes in filter E2E handlebars

* Update the Product Filters testing pages title

* Satisfy TS by returning single React element rather than array of elements

* Revert some incorrect changes

* Cleanup after accidental incorrect merge

* Add template utils to dynamic contents util

* Fix Attribute Filter tests

* Cleanup Attribute tests, refactor and fix types

* Add product filter on top of attirbute filter in handlebars

* Fix lint

* Update Rating filter tests to use Product Archive template instead of post

* Update Rating Filter handlebars

* Update Stock filter tests to use Product Archive template instead of post

* Update Stock Filter handlebars

* Add more granular util to update Produyct Catalog based on handlebar template

* Use Product Catalog util and simplify test scenarios

* Unify handlebar templates

* Fix Product Collection attributes in Product Filter handlebar templates

* Revert temporary timeouts increase

* Remove unused types

* Cleanup types

* Cleanup types

* Lint fix

* Rename updateTemplatesContent to updateTemplateContents to better depict its purpose

* Fix types

* Rename updateProductCatalogContent to updateProductCatalogTemplate to better depict its purpose

* Allow for beforeAll and afterAll in PW tests

* Use beforeAll and afterAll instead of using fixture in active filters test

* Use beforeAll and afterAll instead of using fixture in attribute filters test

* Use beforeAll and afterAll instead of using fixture in price filters test

* Use beforeAll and afterAll instead of using fixture in rating filters test

* Use beforeAll and afterAll instead of using fixture in stock status filters test

* Get rid of updateProductCatalogTemplate util as it's too specific

* Extract some constants

* Remove unused file probably added here by accident

* Adjust Attribute Filter block tests to the new logic

* Merge fix

* Bring back necessary handlebars file

* Merge fix

* Merge fix

* Update beforeAll

* Avoid relying on product collection page object in before all

* Bring back the original order of tests

* Switch Filter by Attribute tests to handlebars

* Fix typo

* Update test to new circumstances

* Fix hooks usage
We no longer use hooks other than `beforeEach` since we're resetting the DB for each test (#46125). Using other hooks was not caught by the linter (on this PR) because I accidentally removed the no-hooks rule in #47228 and restored it just now in #47500. 😅

* Fix the test

* Fix Price filter test

* Update attribute filter tests

* Share the handlebars between tests

* Update price filter tests

* Update rating filter tests

* Update stock filter tests

* Remove unnecessary product collection page object from filter tests

* Fix typo

* Fix Filter by Stock test

* Simplify Attribute filter test by remoiving one filter from page

* Try to wait for element to be visible

* Fix handlebars syntax for filters so it doesnt throw validation errors and warnings

* Wait for filters to be visible for sure before performing further part of test

* Wait for Site Editor canvas loader

* Fix linter error

---------

Co-authored-by: Bart Kalisz <bartlomiej.kalisz@gmail.com>
This commit is contained in:
Karol Manijak 2024-05-17 11:23:56 +02:00 committed by GitHub
parent 5427aa5de8
commit 40b43e8d9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 508 additions and 593 deletions

View File

@ -30,10 +30,12 @@ import { Post } from '@wordpress/e2e-test-utils-playwright/build-types/request-u
* Internal dependencies
*/
import {
PostPayload,
type PostPayload,
createPostFromTemplate,
updateTemplateContents,
deletePost,
} from '../utils/create-dynamic-content';
import type { ExtendedTemplate } from '../types/e2e-test-utils-playwright';
/**
* Set of console logging types observed to protect against unexpected yet
@ -142,6 +144,11 @@ const test = base.extend<
data: unknown
) => Promise< Post >;
deletePost: ( id: number ) => Promise< void >;
updateTemplateContents: (
templateId: string,
templatePath: string,
data: unknown
) => Promise< ExtendedTemplate >;
};
}
>( {
@ -216,9 +223,22 @@ const test = base.extend<
const utilDeletePost = ( id: number ) =>
deletePost( requestUtils, id );
const utilUpdateTemplateContents = (
templateId: string,
templatePath: string,
data: unknown
) =>
updateTemplateContents(
requestUtils,
templateId,
templatePath,
data
);
await use( {
...requestUtils,
createPostFromTemplate: utilCreatePostFromTemplate,
updateTemplateContents: utilUpdateTemplateContents,
deletePost: utilDeletePost,
} );
},

View File

@ -1,13 +1,15 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import path from 'path';
/**
* Internal dependencies
*/
import ProductCollectionPage from '../product-collection/product-collection.page';
const PRODUCT_CATALOG_LINK = '/shop';
const TEMPLATE_PATH = path.join(
__dirname,
'../shared/filters-with-product-collection.handlebars'
);
const blockData = {
name: 'Filter by Attribute',
@ -15,24 +17,6 @@ const blockData = {
urlSearchParamWhenFilterIsApplied: 'filter_size=small&query_type_size=or',
};
const test = base.extend< {
productCollectionPageObject: ProductCollectionPage;
} >( {
productCollectionPageObject: async (
{ page, admin, editor, templateApiUtils, editorUtils },
use
) => {
const pageObject = new ProductCollectionPage( {
page,
admin,
editor,
templateApiUtils,
editorUtils,
} );
await use( pageObject );
},
} );
test.describe( `${ blockData.name } Block`, () => {
test.beforeEach( async ( { admin, editor, editorUtils } ) => {
await admin.createNewPost();
@ -145,7 +129,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
await attributeFilter.getByText( 'Done' ).click();
await editor.saveSiteEditorEntities();
await page.goto( `/shop` );
await page.goto( PRODUCT_CATALOG_LINK );
} );
test( 'should show all products', async ( { frontendUtils, page } ) => {
@ -195,48 +179,27 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
} );
test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test.beforeEach(
async ( {
admin,
editorUtils,
productCollectionPageObject,
editor,
} ) => {
await admin.createNewPost();
await productCollectionPageObject.insertProductCollection();
await productCollectionPageObject.chooseCollectionInPost(
'productCatalog'
);
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
attributes: {
filterType: 'attribute-filter',
heading: 'Filter By Attribute',
},
} );
const attributeFilter = await editorUtils.getBlockByName(
blockData.slug
);
await attributeFilter.getByText( 'Size' ).click();
await attributeFilter.getByText( 'Done' ).click();
await editorUtils.publishAndVisitPost();
}
);
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
'woocommerce/woocommerce//archive-product',
TEMPLATE_PATH,
{}
);
} );
test( 'should show all products', async ( { page } ) => {
await page.goto( PRODUCT_CATALOG_LINK );
const products = page
.locator( '.wp-block-woocommerce-product-template' )
.getByRole( 'listitem' );
await expect( products ).toHaveCount( 9 );
await expect( products ).toHaveCount( 16 );
} );
test( 'should show only products that match the filter', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.getByRole( 'checkbox', { name: 'Small' } ).click();
await expect( page ).toHaveURL(
@ -255,30 +218,24 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
admin,
editor,
editorUtils,
productCollectionPageObject,
} ) => {
await admin.createNewPost();
await productCollectionPageObject.insertProductCollection();
await productCollectionPageObject.chooseCollectionInPost(
'productCatalog'
);
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
attributes: {
filterType: 'attribute-filter',
heading: 'Filter By Attribute',
},
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
const attributeFilterControl = await editorUtils.getBlockByName(
blockData.slug
);
await attributeFilterControl.getByText( 'Size' ).click();
await attributeFilterControl.getByText( 'Done' ).click();
await expect( attributeFilterControl ).toBeVisible();
await editor.selectBlocks( attributeFilterControl );
await editor.openDocumentSettingsSidebar();
await page.getByText( "Show 'Apply filters' button" ).click();
await editorUtils.publishAndVisitPost();
await editor.saveSiteEditorEntities();
await page.goto( PRODUCT_CATALOG_LINK );
await page.getByRole( 'checkbox', { name: 'Small' } ).click();
await page.getByRole( 'button', { name: 'Apply' } ).click();

View File

@ -5,7 +5,10 @@ import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { Post } from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/posts';
import path from 'path';
const TEMPLATE_PATH = path.join( __dirname, './active-filters.handlebars' );
const TEMPLATE_PATH = path.join(
__dirname,
'./filters-with-all-products.handlebars'
);
const test = base.extend< {
defaultBlockPost: Post;

View File

@ -1,34 +1,30 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { Post } from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/posts';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './active-filters.handlebars' );
const test = base.extend< {
defaultBlockPost: Post;
} >( {
defaultBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
{ title: 'Active Filters Block' },
TEMPLATE_PATH,
{}
);
await use( testingPost );
await requestUtils.deletePost( testingPost.id );
},
} );
test.describe( 'Product Filter: Active Filters Block', () => {
test.describe( 'frontend', () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{}
);
} );
test( 'Without any filters selected, only a wrapper block is rendered', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const locator = page.locator(
'.wp-block-woocommerce-product-filter'
@ -42,9 +38,8 @@ test.describe( 'Product Filter: Active Filters Block', () => {
test( 'With rating filters applied it shows the correct active filters', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( `${ defaultBlockPost.link }?rating_filter=1,2,5` );
await page.goto( `${ PRODUCT_CATALOG_LINK }?rating_filter=1,2,5` );
await expect( page.getByText( 'Rating:' ) ).toBeVisible();
await expect( page.getByText( 'Rated 1 out of 5' ) ).toBeVisible();
@ -54,10 +49,9 @@ test.describe( 'Product Filter: Active Filters Block', () => {
test( 'With stock filters applied it shows the correct active filters', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?filter_stock_status=instock,onbackorder`
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=instock,onbackorder`
);
await expect( page.getByText( 'Stock Status:' ) ).toBeVisible();
@ -67,10 +61,9 @@ test.describe( 'Product Filter: Active Filters Block', () => {
test( 'With attribute filters applied it shows the correct active filters', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?filter_color=blue,gray&query_type_color=or`
`${ PRODUCT_CATALOG_LINK }?filter_color=blue,gray&query_type_color=or`
);
await expect( page.getByText( 'Color:' ) ).toBeVisible();
@ -80,10 +73,9 @@ test.describe( 'Product Filter: Active Filters Block', () => {
test( 'With price filters applied it shows the correct active filters', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?min_price=17&max_price=71`
`${ PRODUCT_CATALOG_LINK }?min_price=17&max_price=71`
);
await expect( page.getByText( 'Price:' ) ).toBeVisible();

View File

@ -1,4 +1,12 @@
<!-- wp:woocommerce/product-collection {"id":"bee7a337-f64e-4efd-be51-e68670b10000","queryId":0,"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":false,"taxQuery":{},"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true}} -->
<!-- wp:woocommerce/product-filter {"filterType":"active-filters","heading":"Active filters"} -->
<!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Active filters</h3>
<!-- /wp:heading -->
{{#> wp-block blockName='woocommerce/product-filter-active' attributes=attributes }}
{{/ wp-block }}
<!-- wp:woocommerce/product-collection {"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":true,"taxQuery":[],"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true},"queryContextIncludes":["collection"]} -->
<div class='wp-block-woocommerce-product-collection'>
<!-- wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-image {"imageSizing":"thumbnail","isDescendentOfQueryLoop":true} /-->
@ -9,13 +17,5 @@
<!-- wp:woocommerce/product-button {"textAlign":"center","isDescendentOfQueryLoop":true,"fontSize":"small"} /-->
<!-- /wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-filter {"filterType":"active-filters","heading":"Active filters"} -->
<!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Active filters</h3>
<!-- /wp:heading -->
{{#> wp-block blockName='woocommerce/product-filter-active' attributes=attributes }}
{{/ wp-block }}
</div>
<!-- /wp:woocommerce/product-collection -->

View File

@ -1,9 +1,13 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
import { Post } from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/posts';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './attribute-filter.handlebars' );
@ -17,91 +21,24 @@ const COLOR_ATTRIBUTES_WITH_COUNTS = [
'Yellow (1)',
];
const test = base.extend< {
postWithShowCounts: Post;
defaultBlockPost: Post;
dropdownBlockPost: Post;
} >( {
defaultBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
{ title: 'Product Filter: Attribute Block - Color' },
TEMPLATE_PATH,
{
attributes: {
attributeId: 1,
},
}
);
await use( testingPost );
await requestUtils.deletePost( testingPost.id );
},
postWithShowCounts: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
{ title: 'Product Filter: Attribute Block - Color' },
TEMPLATE_PATH,
{
attributes: {
attributeId: 1,
showCounts: true,
},
}
);
await use( testingPost );
await requestUtils.deletePost( testingPost.id );
},
dropdownBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
{ title: 'Product Filter: Attribute Block' },
TEMPLATE_PATH,
{
attributes: {
attributeId: 1,
displayStyle: 'dropdown',
},
}
);
await use( testingPost );
await requestUtils.deletePost( testingPost.id );
},
} );
test.describe( 'Product Filter: Attribute Block', () => {
test.describe( 'With default display style', () => {
test.describe( 'With show counts enabled', () => {
test( 'Renders checkboxes with associated product counts', async ( {
page,
postWithShowCounts,
} ) => {
await page.goto( postWithShowCounts.link );
const attributes = page.locator(
'.wc-block-components-checkbox__label'
);
await expect( attributes ).toHaveCount( 5 );
for (
let i = 0;
i < COLOR_ATTRIBUTES_WITH_COUNTS.length;
i++
) {
await expect( attributes.nth( i ) ).toHaveText(
COLOR_ATTRIBUTES_WITH_COUNTS[ i ]
);
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
attributes: {
attributeId: 1,
},
}
} );
);
} );
test( 'clear button is not shown on initial page load', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -110,9 +47,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'renders a checkbox list with the available attribute filters', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const attributes = page.locator(
'.wc-block-components-checkbox__label'
@ -129,9 +65,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'filters the list of products by selecting an attribute', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const grayCheckbox = page.getByText( 'Gray' );
await grayCheckbox.click();
@ -146,9 +81,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const grayCheckbox = page.getByText( 'Gray' );
await grayCheckbox.click();
@ -163,9 +97,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const grayCheckbox = page.getByText( 'Gray' );
await grayCheckbox.click();
@ -182,9 +115,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const grayCheckbox = page.getByText( 'Gray' );
await grayCheckbox.click();
@ -206,12 +138,57 @@ test.describe( 'Product Filter: Attribute Block', () => {
} );
} );
test.describe( 'With show counts enabled', () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
attributes: {
attributeId: 1,
showCounts: true,
},
}
);
} );
test( 'Renders checkboxes with associated product counts', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
const attributes = page.locator(
'.wc-block-components-checkbox__label'
);
await expect( attributes ).toHaveCount( 5 );
for ( let i = 0; i < COLOR_ATTRIBUTES_WITH_COUNTS.length; i++ ) {
await expect( attributes.nth( i ) ).toHaveText(
COLOR_ATTRIBUTES_WITH_COUNTS[ i ]
);
}
} );
} );
test.describe( "With display style 'dropdown'", () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
attributes: {
attributeId: 1,
displayStyle: 'dropdown',
},
}
);
} );
test( 'clear button is not shown on initial page load', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto( dropdownBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -220,9 +197,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'renders a dropdown list with the available attribute filters', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto( dropdownBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -240,9 +216,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'Clicking a dropdown option should filter the displayed products', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto( dropdownBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -264,9 +239,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto( dropdownBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -288,9 +262,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto( dropdownBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -319,9 +292,8 @@ test.describe( 'Product Filter: Attribute Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto( dropdownBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'

View File

@ -1,4 +1,19 @@
<!-- wp:woocommerce/product-collection {"id":"bee7a337-f64e-4efd-be51-e68670b10000","queryId":0,"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":false,"taxQuery":{},"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true}} -->
<!-- wp:woocommerce/product-filter {"filterType":"attribute-filter","heading":"Filter by Attribute"} -->
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Filter by Attribute</h3>
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons"><!-- wp:button {"style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"},"className":"wc-block-product-filter-clear-button is-style-outline"} -->
<div class="wp-block-button wc-block-product-filter-clear-button is-style-outline" style="text-decoration:underline"><a class="wp-block-button__link wp-element-button" style="border-style:none;border-width:0px">Clear</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button -->
<!-- /wp:heading -->
{{#> wp-block blockName='woocommerce/product-filter-attribute' attributes=attributes }}
{{/ wp-block }}
<!-- wp:woocommerce/product-collection {"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":true,"taxQuery":[],"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true},"queryContextIncludes":["collection"]} -->
<div class="wp-block-woocommerce-product-collection">
<!-- wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-image {"imageSizing":"thumbnail","isDescendentOfQueryLoop":true} /-->
@ -9,21 +24,5 @@
<!-- wp:woocommerce/product-button {"textAlign":"center","isDescendentOfQueryLoop":true,"fontSize":"small"} /-->
<!-- /wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-filter {"filterType":"rating-filter","heading":"Filter by Rating"} -->
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Filter by Attribute</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons"><!-- wp:button {"style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"},"className":"wc-block-product-filter-clear-button is-style-outline"} -->
<div class="wp-block-button wc-block-product-filter-clear-button is-style-outline" style="text-decoration:underline"><a class="wp-block-button__link wp-element-button" style="border-style:none;border-width:0px">Clear</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button -->
{{#> wp-block blockName='woocommerce/product-filter-attribute' attributes=attributes }}
{{/ wp-block }}
</div>
<!-- /wp:woocommerce/product-collection -->

View File

@ -0,0 +1,3 @@
export const PRODUCT_CATALOG_LINK = '/shop';
export const PRODUCT_CATALOG_TEMPLATE_ID =
'woocommerce/woocommerce//archive-product';

View File

@ -1,34 +1,30 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { Post } from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/posts';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './price-filter.handlebars' );
const test = base.extend< {
defaultBlockPost: Post;
} >( {
defaultBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
{ title: 'Price Filter Block' },
TEMPLATE_PATH,
{}
);
await use( testingPost );
await requestUtils.deletePost( testingPost.id );
},
} );
test.describe( 'Product Filter: Price Filter Block', () => {
test.describe( 'frontend', () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{}
);
} );
test( 'clear button is not shown on initial page load', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -37,10 +33,9 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'With price filters applied it shows the correct price', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?min_price=20&max_price=67`
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
// Min price input field
@ -75,10 +70,9 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?min_price=20&max_price=67`
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -88,10 +82,9 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?min_price=20&max_price=67`
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
const defaultRange = await page
@ -123,17 +116,16 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?min_price=20&max_price=67`
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
const button = page.getByRole( 'button', { name: 'Clear' } );
await button.click();
await page.waitForURL( defaultBlockPost.link );
await page.waitForURL( `${ PRODUCT_CATALOG_LINK }/` );
const defaultRangePrice = await page
.locator( '.wp-block-woocommerce-product-filter-price' )
@ -150,10 +142,9 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'Changes in the price input field triggers price slider updates', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?min_price=20&max_price=67`
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
// Min price input field
@ -192,10 +183,9 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'Price input field rejects min price higher than max price', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?min_price=20&max_price=67`
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
// Min price input field
@ -217,10 +207,9 @@ test.describe( 'Product Filter: Price Filter Block', () => {
test( 'Price input field rejects max price lower than min price', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?min_price=20&max_price=67`
`${ PRODUCT_CATALOG_LINK }?min_price=20&max_price=67`
);
// Max price input field

View File

@ -1,4 +1,19 @@
<!-- wp:woocommerce/product-collection {"id":"bee7a337-f64e-4efd-be51-e68670b10000","queryId":0,"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":false,"taxQuery":{},"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true}} -->
<!-- wp:woocommerce/product-filter {"filterType":"price-filter","heading":"Filter by Price"} -->
<!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Filter by Price</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons"><!-- wp:button {"style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"},"className":"wc-block-product-filter-clear-button is-style-outline"} -->
<div class="wp-block-button wc-block-product-filter-clear-button is-style-outline" style="text-decoration:underline"><a class="wp-block-button__link wp-element-button" style="border-style:none;border-width:0px">Clear</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button -->
{{#> wp-block blockName='woocommerce/product-filter-price' attributes=attributes }}
{{/ wp-block }}
<!-- wp:woocommerce/product-collection {"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":true,"taxQuery":[],"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true},"queryContextIncludes":["collection"]} -->
<div class='wp-block-woocommerce-product-collection'>
<!-- wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-image {"imageSizing":"thumbnail","isDescendentOfQueryLoop":true} /-->
@ -9,21 +24,5 @@
<!-- wp:woocommerce/product-button {"textAlign":"center","isDescendentOfQueryLoop":true,"fontSize":"small"} /-->
<!-- /wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-filter {"filterType":"price-filter","heading":"Filter by Price"} -->
<!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Filter by Price</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons"><!-- wp:button {"style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"},"className":"wc-block-product-filter-clear-button is-style-outline"} -->
<div class="wp-block-button wc-block-product-filter-clear-button is-style-outline" style="text-decoration:underline"><a class="wp-block-button__link wp-element-button" style="border-style:none;border-width:0px">Clear</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button -->
{{#> wp-block blockName='woocommerce/product-filter-price' attributes=attributes }}
{{/ wp-block }}
</div>
<!-- /wp:woocommerce/product-collection -->

View File

@ -1,34 +1,34 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { Post } from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/posts';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './rating-filter.handlebars' );
const test = base.extend< {
defaultBlockPost: Post;
} >( {
defaultBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
{ title: 'Active Filters Block' },
TEMPLATE_PATH,
{}
);
await use( testingPost );
await requestUtils.deletePost( testingPost.id );
},
} );
test.describe( 'Product Filter: Rating Filter Block', () => {
test.describe( 'frontend', () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
attributes: {
attributeId: 1,
},
}
);
} );
test( 'clear button is not shown on initial page load', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -37,9 +37,8 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( `${ defaultBlockPost.link }?rating_filter=1` );
await page.goto( `${ PRODUCT_CATALOG_LINK }?rating_filter=1` );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -48,9 +47,8 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( `${ defaultBlockPost.link }?rating_filter=1` );
await page.goto( `${ PRODUCT_CATALOG_LINK }?rating_filter=1` );
const ratingCheckboxes = page.getByLabel(
/Checkbox: Rated \d out of 5/
@ -65,9 +63,8 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( `${ defaultBlockPost.link }?rating_filter=1` );
await page.goto( `${ PRODUCT_CATALOG_LINK }?rating_filter=1` );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -83,9 +80,8 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'Renders a checkbox list with the available ratings', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const ratingStars = page.getByLabel( /^Rated \d out of 5/ );
await expect( ratingStars ).toHaveCount( 2 );
@ -103,9 +99,8 @@ test.describe( 'Product Filter: Rating Filter Block', () => {
test( 'Selecting a checkbox filters down the products', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const ratingCheckboxes = page.getByLabel(
/Checkbox: Rated \d out of 5/

View File

@ -1,4 +1,20 @@
<!-- wp:woocommerce/product-collection {"id":"bee7a337-f64e-4efd-be51-e68670b10000","queryId":0,"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":false,"taxQuery":{},"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true}} -->
<!-- wp:woocommerce/product-filter {"filterType":"rating-filter","heading":"Filter by Rating"} -->
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Filter by Rating</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons"><!-- wp:button {"style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"},"className":"wc-block-product-filter-clear-button is-style-outline"} -->
<div class="wp-block-button wc-block-product-filter-clear-button is-style-outline" style="text-decoration:underline"><a class="wp-block-button__link wp-element-button" style="border-style:none;border-width:0px">Clear</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button -->
{{#> wp-block blockName='woocommerce/product-filter-rating' attributes=attributes }}
{{/ wp-block }}
<!-- wp:woocommerce/product-collection {"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":true,"taxQuery":[],"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true},"queryContextIncludes":["collection"]} -->
<div class="wp-block-woocommerce-product-collection">
<!-- wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-image {"imageSizing":"thumbnail","isDescendentOfQueryLoop":true} /-->
@ -9,21 +25,5 @@
<!-- wp:woocommerce/product-button {"textAlign":"center","isDescendentOfQueryLoop":true,"fontSize":"small"} /-->
<!-- /wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-filter {"filterType":"rating-filter","heading":"Filter by Rating"} -->
<!-- wp:heading {"level":3} -->
<h3 class="wp-block-heading">Filter by Rating</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons"><!-- wp:button {"style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"},"className":"wc-block-product-filter-clear-button is-style-outline"} -->
<div class="wp-block-button wc-block-product-filter-clear-button is-style-outline" style="text-decoration:underline"><a class="wp-block-button__link wp-element-button" style="border-style:none;border-width:0px">Clear</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button -->
{{#> wp-block blockName='woocommerce/product-filter-rating' attributes=attributes }}
{{/ wp-block }}
</div>
<!-- /wp:woocommerce/product-collection -->

View File

@ -1,50 +1,30 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import path from 'path';
import { Post } from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/posts';
/**
* Internal dependencies
*/
import { PRODUCT_CATALOG_LINK, PRODUCT_CATALOG_TEMPLATE_ID } from './constants';
const TEMPLATE_PATH = path.join( __dirname, './stock-status.handlebars' );
const test = base.extend< {
dropdownBlockPost: Post;
defaultBlockPost: Post;
} >( {
defaultBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
{ title: 'Product Filter Stock Status Block' },
TEMPLATE_PATH,
{}
);
await use( testingPost );
await requestUtils.deletePost( testingPost.id );
},
dropdownBlockPost: async ( { requestUtils }, use ) => {
const testingPost = await requestUtils.createPostFromTemplate(
{ title: 'Product Filter Stock Status Block' },
TEMPLATE_PATH,
{
attributes: {
displayStyle: 'dropdown',
},
}
);
await use( testingPost );
await requestUtils.deletePost( testingPost.id );
},
} );
test.describe( 'Product Filter: Stock Status Block', () => {
test.describe( 'With default display style', () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{}
);
} );
test( 'clear button is not shown on initial page load', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -53,9 +33,8 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'renders a checkbox list with the available stock statuses', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const stockStatuses = page.locator(
'.wc-block-components-checkbox__label'
@ -68,9 +47,8 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'filters the list of products by selecting a stock status', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const outOfStockCheckbox = page.getByText( 'Out of stock' );
await outOfStockCheckbox.click();
@ -85,9 +63,8 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const outOfStockCheckbox = page.getByText( 'Out of stock' );
await outOfStockCheckbox.click();
@ -102,10 +79,9 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?filter_stock_status=outofstock`
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=outofstock`
);
const outOfStockCheckbox = page.getByText( 'Out of stock' );
@ -118,10 +94,9 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto(
`${ defaultBlockPost.link }?filter_stock_status=outofstock`
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=outofstock`
);
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -137,11 +112,22 @@ test.describe( 'Product Filter: Stock Status Block', () => {
} );
test.describe( 'With dropdown display style', () => {
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
PRODUCT_CATALOG_TEMPLATE_ID,
TEMPLATE_PATH,
{
attributes: {
displayStyle: 'dropdown',
},
}
);
} );
test( 'clear button is not shown on initial page load', async ( {
page,
defaultBlockPost,
} ) => {
await page.goto( defaultBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const button = page.getByRole( 'button', { name: 'Clear' } );
@ -150,9 +136,8 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'a dropdown is displayed with the available stock statuses', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto( dropdownBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -167,9 +152,8 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'clear button appears after a filter is applied', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto( dropdownBlockPost.link );
await page.goto( PRODUCT_CATALOG_LINK );
const dropdownLocator = page.locator(
'.wc-interactivity-dropdown'
@ -189,10 +173,9 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'clear button hides after deselecting all filters', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto(
`${ dropdownBlockPost.link }?filter_stock_status=instock`
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=instock`
);
const dropdownLocator = page.locator(
@ -214,10 +197,9 @@ test.describe( 'Product Filter: Stock Status Block', () => {
test( 'filters are cleared after clear button is clicked', async ( {
page,
dropdownBlockPost,
} ) => {
await page.goto(
`${ dropdownBlockPost.link }?filter_stock_status=instock`
`${ PRODUCT_CATALOG_LINK }?filter_stock_status=instock`
);
const button = page.getByRole( 'button', { name: 'Clear' } );

View File

@ -1,4 +1,19 @@
<!-- wp:woocommerce/product-collection {"id":"bee7a337-f64e-4efd-be51-e68670b10000","queryId":0,"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":false,"taxQuery":{},"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true}} -->
<!-- wp:woocommerce/product-filter {"filterType":"stock-filter","heading":"Filter by Stock Status"} -->
<!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Filter by Stock Status</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons"><!-- wp:button {"style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"},"className":"wc-block-product-filter-clear-button is-style-outline"} -->
<div class="wp-block-button wc-block-product-filter-clear-button is-style-outline" style="text-decoration:underline"><a class="wp-block-button__link wp-element-button" style="border-style:none;border-width:0px">Clear</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button -->
{{#> wp-block blockName='woocommerce/product-filter-stock-status' attributes=attributes }}
{{/ wp-block }}
<!-- wp:woocommerce/product-collection {"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":true,"taxQuery":[],"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true},"queryContextIncludes":["collection"]} -->
<div class='wp-block-woocommerce-product-collection'>
<!-- wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-image {"imageSizing":"thumbnail","isDescendentOfQueryLoop":true} /-->
@ -9,22 +24,5 @@
<!-- wp:woocommerce/product-button {"textAlign":"center","isDescendentOfQueryLoop":true,"fontSize":"small"} /-->
<!-- /wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-filter {"filterType":"stock-filter","heading":"Filter by Stock Status"} -->
<!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Filter by Stock Status</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/product-filter-clear-button {"lock":{"remove":true,"move":false}} -->
<!-- wp:buttons {"layout":{"type":"flex"}} -->
<div class="wp-block-buttons"><!-- wp:button {"style":{"border":{"width":"0px","style":"none"},"typography":{"textDecoration":"underline"},"outline":"none","fontSize":"medium"},"className":"wc-block-product-filter-clear-button is-style-outline"} -->
<div class="wp-block-button wc-block-product-filter-clear-button is-style-outline" style="text-decoration:underline"><a class="wp-block-button__link wp-element-button" style="border-style:none;border-width:0px">Clear</a></div>
<!-- /wp:button --></div>
<!-- /wp:buttons -->
<!-- /wp:woocommerce/product-filter-clear-button -->
{{#> wp-block blockName='woocommerce/product-filter-stock-status' attributes=attributes }}
{{/ wp-block }}
</div>
<!-- /wp:woocommerce/product-collection -->

View File

@ -1,13 +1,15 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { BASE_URL, cli } from '@woocommerce/e2e-utils';
import path from 'path';
/**
* Internal dependencies
*/
import ProductCollectionPage from '../product-collection/product-collection.page';
const PRODUCT_CATALOG_LINK = '/shop';
const TEMPLATE_PATH = path.join(
__dirname,
'../shared/filters-with-product-collection.handlebars'
);
export const blockData = {
slug: 'woocommerce/price-filter',
@ -22,24 +24,6 @@ export const blockData = {
placeholderUrl: `${ BASE_URL }/wp-content/plugins/woocommerce/assets/images/placeholder.png`,
};
const test = base.extend< {
productCollectionPageObject: ProductCollectionPage;
} >( {
productCollectionPageObject: async (
{ page, admin, editor, templateApiUtils, editorUtils },
use
) => {
const pageObject = new ProductCollectionPage( {
page,
admin,
editor,
templateApiUtils,
editorUtils,
} );
await use( pageObject );
},
} );
test.describe( `${ blockData.name } Block - editor side`, () => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.createNewPost();
@ -299,42 +283,28 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
} );
test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test.beforeEach(
async ( {
admin,
editorUtils,
productCollectionPageObject,
editor,
} ) => {
await admin.createNewPost();
await productCollectionPageObject.insertProductCollection();
await productCollectionPageObject.chooseCollectionInPost(
'productCatalog'
);
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
attributes: {
filterType: 'price-filter',
heading: 'Filter By Price',
},
} );
await editorUtils.publishAndVisitPost();
}
);
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
'woocommerce/woocommerce//archive-product',
TEMPLATE_PATH,
{}
);
} );
test( 'should show all products', async ( { page } ) => {
await page.goto( PRODUCT_CATALOG_LINK );
const products = page
.locator( '.wp-block-woocommerce-product-template' )
.getByRole( 'listitem' );
await expect( products ).toHaveCount( 9 );
await expect( products ).toHaveCount( 16 );
} );
test( 'should show only products that match the filter', async ( {
page,
frontendUtils,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
const maxPriceInput = page.getByRole( 'textbox', {
name: 'Filter products by maximum price',
} );
@ -353,34 +323,29 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
await expect( products ).toHaveCount( 1 );
} );
test( 'should refresh the page only if the user click on button', async ( {
test( 'should refresh the page only if the user clicks on button', async ( {
page,
admin,
editor,
editorUtils,
productCollectionPageObject,
} ) => {
await admin.createNewPost();
await productCollectionPageObject.insertProductCollection();
await productCollectionPageObject.chooseCollectionInPost(
'productCatalog'
);
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
attributes: {
filterType: 'price-filter',
heading: 'Filter By Price',
},
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
const priceFilterControls = await editorUtils.getBlockByName(
blockData.slug
);
await expect( priceFilterControls ).toBeVisible();
await editor.selectBlocks( priceFilterControls );
await editor.openDocumentSettingsSidebar();
await page.getByText( "Show 'Apply filters' button" ).click();
await editorUtils.publishAndVisitPost();
await editor.saveSiteEditorEntities();
await page.goto( PRODUCT_CATALOG_LINK );
const maxPriceInput = page.getByRole( 'textbox', {
name: 'Filter products by maximum price',

View File

@ -1,13 +1,15 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import path from 'path';
/**
* Internal dependencies
*/
import ProductCollectionPage from '../product-collection/product-collection.page';
const PRODUCT_CATALOG_LINK = '/shop';
const TEMPLATE_PATH = path.join(
__dirname,
'../shared/filters-with-product-collection.handlebars'
);
const blockData = {
name: 'Filter by Rating',
@ -15,24 +17,6 @@ const blockData = {
urlSearchParamWhenFilterIsApplied: 'rating_filter=1',
};
const test = base.extend< {
productCollectionPageObject: ProductCollectionPage;
} >( {
productCollectionPageObject: async (
{ page, admin, editor, templateApiUtils, editorUtils },
use
) => {
const pageObject = new ProductCollectionPage( {
page,
admin,
editor,
templateApiUtils,
editorUtils,
} );
await use( pageObject );
},
} );
test.describe( `${ blockData.name } Block`, () => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.createNewPost();
@ -130,6 +114,7 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
heading: 'Filter By Rating',
},
} );
await editor.saveSiteEditorEntities();
await page.goto( `/shop` );
} );
@ -175,40 +160,27 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
} );
test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test.beforeEach(
async ( {
admin,
editorUtils,
productCollectionPageObject,
editor,
} ) => {
await admin.createNewPost();
await productCollectionPageObject.insertProductCollection();
await productCollectionPageObject.chooseCollectionInPost(
'productCatalog'
);
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
attributes: {
filterType: 'rating-filter',
heading: 'Filter By Rating',
},
} );
await editorUtils.publishAndVisitPost();
}
);
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
'woocommerce/woocommerce//archive-product',
TEMPLATE_PATH,
{}
);
} );
test( 'should show all products', async ( { page } ) => {
await page.goto( PRODUCT_CATALOG_LINK );
const products = page
.locator( '.wp-block-woocommerce-product-template' )
.getByRole( 'listitem' );
await expect( products ).toHaveCount( 9 );
await expect( products ).toHaveCount( 16 );
} );
test( 'should show only products that match the filter', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page
.getByRole( 'checkbox', { name: 'Rated 1 out of 5' } )
.click();
@ -224,33 +196,29 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
await expect( products ).toHaveCount( 1 );
} );
test( 'should refresh the page only if the user click on button', async ( {
test( 'should refresh the page only if the user clicks on button', async ( {
page,
admin,
editor,
editorUtils,
productCollectionPageObject,
} ) => {
await admin.createNewPost();
await productCollectionPageObject.insertProductCollection();
await productCollectionPageObject.chooseCollectionInPost(
'productCatalog'
);
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
attributes: {
filterType: 'rating-filter',
heading: 'Filter By Rating',
},
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
const ratingFilterControls = await editorUtils.getBlockByName(
'woocommerce/rating-filter'
);
await expect( ratingFilterControls ).toBeVisible();
await editor.selectBlocks( ratingFilterControls );
await editor.openDocumentSettingsSidebar();
await page.getByText( "Show 'Apply filters' button" ).click();
await editorUtils.publishAndVisitPost();
await editor.saveSiteEditorEntities();
await page.goto( PRODUCT_CATALOG_LINK );
await page
.getByRole( 'checkbox', { name: 'Rated 1 out of 5' } )

View File

@ -0,0 +1,82 @@
<!-- wp:columns -->
<div class='wp-block-columns'>
<!-- wp:column {"width":"33.33%"} -->
<div class='wp-block-column' style='flex-basis:33.33%'>
<!-- wp:woocommerce/filter-wrapper {"filterType":"active-filters","heading":"Active filters"} -->
<div class='wp-block-woocommerce-filter-wrapper'>
<!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Active filters</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/active-filters {"heading":"","lock":{"remove":true}} -->
<div class="wp-block-woocommerce-active-filters is-loading"><span aria-hidden="true" class="wc-block-active-filters__placeholder"></span></div>
<!-- /wp:woocommerce/active-filters -->
</div>
<!-- /wp:woocommerce/filter-wrapper -->
<!-- wp:woocommerce/filter-wrapper {"filterType":"price-filter","heading":"Filter by price"} -->
<div class='wp-block-woocommerce-filter-wrapper'><!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Filter by price</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/price-filter {"heading":"","lock":{"remove":true}} -->
<div class="wp-block-woocommerce-price-filter is-loading"><span aria-hidden="true" class="wc-block-product-categories__placeholder"></span></div>
<!-- /wp:woocommerce/price-filter -->
</div>
<!-- /wp:woocommerce/filter-wrapper -->
<!-- wp:woocommerce/filter-wrapper {"filterType":"stock-filter","heading":"Filter by stock status"} -->
<div class='wp-block-woocommerce-filter-wrapper'><!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Filter by stock status</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/stock-filter {"heading":"","lock":{"remove":true}} -->
<div class="wp-block-woocommerce-stock-filter is-loading"></div>
<!-- /wp:woocommerce/stock-filter -->
</div>
<!-- /wp:woocommerce/filter-wrapper -->
<!-- wp:woocommerce/filter-wrapper {"filterType":"rating-filter","heading":"Filter by rating"} -->
<div class='wp-block-woocommerce-filter-wrapper'>
<!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Filter by rating</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/rating-filter {"lock":{"remove":true}} -->
<div class="wp-block-woocommerce-rating-filter is-loading"></div>
<!-- /wp:woocommerce/rating-filter -->
</div>
<!-- /wp:woocommerce/filter-wrapper -->
<!-- wp:woocommerce/filter-wrapper {"filterType":"attribute-filter","heading":"Filter by attribute"} -->
<div class='wp-block-woocommerce-filter-wrapper'>
<!-- wp:heading {"level":3} -->
<h3 class='wp-block-heading'>Filter by attribute</h3>
<!-- /wp:heading -->
<!-- wp:woocommerce/attribute-filter {"attributeId":2,"heading":"","lock":{"remove":true}} -->
<div class="wp-block-woocommerce-attribute-filter is-loading"></div>
<!-- /wp:woocommerce/attribute-filter -->
</div>
<!-- /wp:woocommerce/filter-wrapper -->
</div>
<!-- /wp:column -->
<!-- wp:column {"width":"66.66%"} -->
<div class='wp-block-column' style='flex-basis:66.66%'>
<!-- wp:woocommerce/product-collection {"query":{"perPage":9,"pages":0,"offset":0,"postType":"product","order":"asc","orderBy":"title","search":"","exclude":[],"inherit":true,"taxQuery":[],"isProductCollectionBlock":true,"featured":false,"woocommerceOnSale":false,"woocommerceStockStatus":["instock","outofstock","onbackorder"],"woocommerceAttributes":[],"woocommerceHandPickedProducts":[]},"tagName":"div","displayLayout":{"type":"flex","columns":3,"shrinkColumns":true},"queryContextIncludes":["collection"]} -->
<div class="wp-block-woocommerce-product-collection">
<!-- wp:woocommerce/product-template -->
<!-- wp:woocommerce/product-image {"imageSizing":"thumbnail","isDescendentOfQueryLoop":true} /-->
<!-- wp:post-title {"textAlign":"center","level":3,"isLink":true,"style":{"spacing":{"margin":{"bottom":"0.75rem","top":"0"}}},"fontSize":"medium","__woocommerceNamespace":"woocommerce/product-collection/product-title"} /-->
<!-- wp:woocommerce/product-price {"isDescendentOfQueryLoop":true,"textAlign":"center","fontSize":"small"} /-->
<!-- wp:woocommerce/product-button {"textAlign":"center","isDescendentOfQueryLoop":true,"fontSize":"small"} /-->
<!-- /wp:woocommerce/product-template -->
</div>
<!-- /wp:woocommerce/product-collection -->
</div>
<!-- /wp:column -->
</div>
<!-- /wp:columns -->

View File

@ -1,13 +1,15 @@
/**
* External dependencies
*/
import { test as base, expect } from '@woocommerce/e2e-playwright-utils';
import { test, expect } from '@woocommerce/e2e-playwright-utils';
import { cli } from '@woocommerce/e2e-utils';
import path from 'path';
/**
* Internal dependencies
*/
import ProductCollectionPage from '../product-collection/product-collection.page';
const PRODUCT_CATALOG_LINK = '/shop';
const TEMPLATE_PATH = path.join(
__dirname,
'../shared/filters-with-product-collection.handlebars'
);
export const blockData = {
name: 'Filter by Stock',
@ -15,24 +17,6 @@ export const blockData = {
urlSearchParamWhenFilterIsApplied: 'filter_stock_status=outofstock',
};
const test = base.extend< {
productCollectionPageObject: ProductCollectionPage;
} >( {
productCollectionPageObject: async (
{ page, admin, editor, templateApiUtils, editorUtils },
use
) => {
const pageObject = new ProductCollectionPage( {
page,
admin,
editor,
templateApiUtils,
editorUtils,
} );
await use( pageObject );
},
} );
test.describe( `${ blockData.name } Block`, () => {
test.beforeEach( async ( { admin, editor } ) => {
await admin.createNewPost();
@ -191,40 +175,27 @@ test.describe( `${ blockData.name } Block - with PHP classic template`, () => {
} );
test.describe( `${ blockData.name } Block - with Product Collection`, () => {
test.beforeEach(
async ( {
admin,
editorUtils,
productCollectionPageObject,
editor,
} ) => {
await admin.createNewPost();
await productCollectionPageObject.insertProductCollection();
await productCollectionPageObject.chooseCollectionInPost(
'productCatalog'
);
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
attributes: {
filterType: 'stock-filter',
heading: 'Filter By Stock',
},
} );
await editorUtils.publishAndVisitPost();
}
);
test.beforeEach( async ( { requestUtils } ) => {
await requestUtils.updateTemplateContents(
'woocommerce/woocommerce//archive-product',
TEMPLATE_PATH,
{}
);
} );
test( 'should show all products', async ( { page } ) => {
await page.goto( PRODUCT_CATALOG_LINK );
const products = page
.locator( '.wp-block-woocommerce-product-template' )
.getByRole( 'listitem' );
await expect( products ).toHaveCount( 9 );
await expect( products ).toHaveCount( 16 );
} );
test( 'should show only products that match the filter', async ( {
page,
} ) => {
await page.goto( PRODUCT_CATALOG_LINK );
await page.getByText( 'Out of Stock' ).click();
await expect( page ).toHaveURL(
@ -238,32 +209,27 @@ test.describe( `${ blockData.name } Block - with Product Collection`, () => {
await expect( products ).toHaveCount( 1 );
} );
test( 'should refresh the page only if the user click on button', async ( {
test( 'should refresh the page only if the user clicks on button', async ( {
page,
admin,
editor,
editorUtils,
productCollectionPageObject,
} ) => {
await admin.createNewPost();
await productCollectionPageObject.insertProductCollection();
await productCollectionPageObject.chooseCollectionInPost(
'productCatalog'
);
await editor.insertBlock( {
name: 'woocommerce/filter-wrapper',
attributes: {
filterType: 'stock-filter',
heading: 'Filter By Price',
},
await admin.visitSiteEditor( {
postId: 'woocommerce/woocommerce//archive-product',
postType: 'wp_template',
} );
await editorUtils.enterEditMode();
const stockFilterControls = await editorUtils.getBlockByName(
blockData.slug
);
await expect( stockFilterControls ).toBeVisible();
await editor.selectBlocks( stockFilterControls );
await editor.openDocumentSettingsSidebar();
await page.getByText( "Show 'Apply filters' button" ).click();
await editorUtils.publishAndVisitPost();
await editor.saveSiteEditorEntities();
await page.goto( PRODUCT_CATALOG_LINK );
await page.getByText( 'Out of Stock' ).click();
await page.getByRole( 'button', { name: 'Apply' } ).click();

View File

@ -0,0 +1,10 @@
/**
* Missing or not exported types from @wordpress/e2e-test-utils-playwright
*/
// import { type Template} from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/templates
export interface Template {
wp_id: number;
id: string;
}
export type ExtendedTemplate = Template & { link: string };

View File

@ -3,17 +3,9 @@
*/
import { readFile } from 'fs/promises';
import Handlebars from 'handlebars';
import {
CreatePostPayload,
Post,
} from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/posts';
import { CreatePostPayload } from '@wordpress/e2e-test-utils-playwright/build-types/request-utils/posts';
import { RequestUtils } from '@wordpress/e2e-test-utils-playwright';
export type TestingPost = {
post: Post;
deletePost: () => Promise< void >;
};
Handlebars.registerPartial(
'wp-block',
`
@ -37,8 +29,6 @@ export const deletePost = async ( requestUtils: RequestUtils, id: number ) => {
} );
};
const posts: number[] = [];
const createPost = async (
requestUtils: RequestUtils,
payload: CreatePostPayload
@ -50,7 +40,6 @@ const createPost = async (
path: `/wp/v2/posts`,
data: { ...payload },
} );
posts.push( post.id );
return post;
};
@ -74,3 +63,23 @@ export const createPostFromTemplate = async (
return createPost( requestUtils, payload );
};
export const updateTemplateContents = async (
requestUtils: RequestUtils,
templateId: string,
templatePath: string,
data: unknown
) => {
const templateContent = await readFile( templatePath, 'utf8' );
const content = Handlebars.compile( templateContent )( data );
const payload = {
content,
};
return requestUtils.rest( {
method: 'POST',
path: `/wp/v2/templates/${ templateId }`,
data: { ...payload },
} );
};

View File

@ -0,0 +1,4 @@
Significance: minor
Type: add
Product Collection: collections that don't inherit query from template are non-filterable

View File

@ -452,7 +452,9 @@ class ProductCollection extends AbstractBlock {
// phpcs:ignore WordPress.DB.SlowDBQuery
$block_context_query['tax_query'] = ! empty( $query['tax_query'] ) ? $query['tax_query'] : array();
return $this->get_final_frontend_query( $block_context_query, $page );
$is_exclude_applied_filters = ! ( $block->context['query']['inherit'] ?? false );
return $this->get_final_frontend_query( $block_context_query, $page, $is_exclude_applied_filters );
}

View File

@ -36,7 +36,7 @@ class ProductCollection extends \WP_UnitTestCase {
'search' => '',
'exclude' => array(),
'sticky' => '',
'inherit' => false,
'inherit' => true,
'isProductCollectionBlock' => true,
'woocommerceAttributes' => array(),
'woocommerceStockStatus' => array(