diff --git a/plugins/woocommerce-blocks/tests/e2e/fixtures/fixture-data.js b/plugins/woocommerce-blocks/tests/e2e/fixtures/fixture-data.js index ceb72ed35f1..af7ae386864 100644 --- a/plugins/woocommerce-blocks/tests/e2e/fixtures/fixture-data.js +++ b/plugins/woocommerce-blocks/tests/e2e/fixtures/fixture-data.js @@ -229,6 +229,29 @@ const Products = () => [ categories: [ 'Music' ], tags: [ 'Newest' ], }, + { + name: 'Woo Single #3 - Limited Edition', + type: 'simple', + regular_price: '100.00', + virtual: true, + downloadable: true, + downloads: [ + { + name: 'Woo Single 2', + file: + 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_4_angle.jpg', + }, + ], + images: [ + { + src: + 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/cd_4_angle.jpg', + }, + ], + categories: [ 'Music' ], + stock_status: 'outofstock', + tags: [ 'Newest' ], + }, ]; /** diff --git a/plugins/woocommerce-blocks/tests/e2e/specs/shopper/filter-products-by-attribute.test.ts b/plugins/woocommerce-blocks/tests/e2e/specs/shopper/filter-products-by-attribute.test.ts index 9ce7b44df65..10b74310d7c 100644 --- a/plugins/woocommerce-blocks/tests/e2e/specs/shopper/filter-products-by-attribute.test.ts +++ b/plugins/woocommerce-blocks/tests/e2e/specs/shopper/filter-products-by-attribute.test.ts @@ -80,7 +80,7 @@ describe( `${ block.name } Block`, () => { await waitForAllProductsBlockLoaded(); const products = await page.$$( selectors.frontend.productsList ); - expect( products ).toHaveLength( 4 ); + expect( products ).toHaveLength( 5 ); } ); it( 'should show only products that match the filter', async () => { @@ -131,7 +131,7 @@ describe( `${ block.name } Block`, () => { selectors.frontend.classicProductsList ); - expect( products ).toHaveLength( 4 ); + expect( products ).toHaveLength( 5 ); } ); it( 'should show only products that match the filter', async () => { diff --git a/plugins/woocommerce-blocks/tests/e2e/specs/shopper/filter-products-by-stock.test.ts b/plugins/woocommerce-blocks/tests/e2e/specs/shopper/filter-products-by-stock.test.ts new file mode 100644 index 00000000000..424b99849cd --- /dev/null +++ b/plugins/woocommerce-blocks/tests/e2e/specs/shopper/filter-products-by-stock.test.ts @@ -0,0 +1,202 @@ +import { + createNewPost, + deleteAllTemplates, + insertBlock, + switchUserToAdmin, + publishPost, +} from '@wordpress/e2e-test-utils'; +import { selectBlockByName } from '@woocommerce/blocks-test-utils'; +import { + BASE_URL, + goToTemplateEditor, + openBlockEditorSettings, + saveTemplate, + useTheme, + waitForCanvas, +} from '../../utils'; + +const block = { + name: 'Filter Products by Stock', + slug: 'woocommerce/stock-filter', + class: '.wc-block-stock-filter', + selectors: { + editor: { + filterButtonToggle: "//label[text()='Filter button']", + }, + frontend: { + productsList: '.wc-block-grid__products > li', + classicProductsList: '.products.columns-3 > li', + filter: 'label[for=outofstock]', + submitButton: '.wc-block-components-filter-submit-button', + }, + }, + urlSearchParamWhenFilterIsApplied: '?filter_stock_status=outofstock', + foundProduct: 'Woo Single #3', +}; + +const { selectors } = block; + +const waitForAllProductsBlockLoaded = () => + page.waitForSelector( selectors.frontend.productsList + '.is-loading', { + hidden: true, + } ); + +const goToShopPage = () => + page.goto( BASE_URL + '/shop', { + waitUntil: 'networkidle0', + } ); + +describe( `${ block.name } Block`, () => { + describe( 'with All Products Block', () => { + let link = ''; + beforeAll( async () => { + await switchUserToAdmin(); + await createNewPost( { + postType: 'post', + title: block.name, + } ); + + await insertBlock( block.name ); + await insertBlock( 'All Products' ); + await publishPost(); + + link = await page.evaluate( () => + wp.data.select( 'core/editor' ).getPermalink() + ); + } ); + + it( 'should render', async () => { + await page.goto( link ); + await waitForAllProductsBlockLoaded(); + const products = await page.$$( selectors.frontend.productsList ); + + expect( products ).toHaveLength( 5 ); + } ); + + it( 'should show only products that match the filter', async () => { + const isRefreshed = jest.fn( () => void 0 ); + page.on( 'load', isRefreshed ); + await page.click( selectors.frontend.filter ); + await waitForAllProductsBlockLoaded(); + const products = await page.$$( selectors.frontend.productsList ); + expect( isRefreshed ).not.toBeCalled(); + expect( products ).toHaveLength( 1 ); + await expect( page ).toMatch( block.foundProduct ); + } ); + } ); + + describe( 'with PHP classic template ', () => { + const productCatalogTemplateId = + 'woocommerce/woocommerce//archive-product'; + + useTheme( 'emptytheme' ); + beforeAll( async () => { + await deleteAllTemplates( 'wp_template' ); + await deleteAllTemplates( 'wp_template_part' ); + await goToTemplateEditor( { + postId: productCatalogTemplateId, + } ); + await insertBlock( block.name ); + await saveTemplate(); + await goToShopPage(); + } ); + + afterAll( async () => { + await deleteAllTemplates( 'wp_template' ); + await deleteAllTemplates( 'wp_template_part' ); + } ); + + it( 'should render', async () => { + const products = await page.$$( + selectors.frontend.classicProductsList + ); + + expect( products ).toHaveLength( 5 ); + } ); + + it( 'should show only products that match the filter', async () => { + const isRefreshed = jest.fn( () => void 0 ); + page.on( 'load', isRefreshed ); + + await page.waitForSelector( block.class + '.is-loading', { + hidden: true, + } ); + + expect( isRefreshed ).not.toBeCalled(); + + await Promise.all( [ + page.waitForNavigation( { + waitUntil: 'networkidle0', + } ), + page.click( selectors.frontend.filter ), + ] ); + + const products = await page.$$( + selectors.frontend.classicProductsList + ); + const pageURL = page.url(); + const parsedURL = new URL( pageURL ); + + expect( isRefreshed ).toBeCalledTimes( 1 ); + expect( products ).toHaveLength( 1 ); + await expect( page ).toMatch( block.foundProduct ); + expect( parsedURL.search ).toEqual( + block.urlSearchParamWhenFilterIsApplied + ); + } ); + + it( 'should refresh the page only if the user click on button', async () => { + await goToTemplateEditor( { + postId: productCatalogTemplateId, + } ); + + await waitForCanvas(); + await selectBlockByName( block.slug ); + await openBlockEditorSettings(); + await page.waitForXPath( + block.selectors.editor.filterButtonToggle + ); + const [ filterButtonToggle ] = await page.$x( + selectors.editor.filterButtonToggle + ); + await filterButtonToggle.click(); + await saveTemplate(); + await goToShopPage(); + + const isRefreshed = jest.fn( () => void 0 ); + page.on( 'load', isRefreshed ); + + await page.waitForSelector( block.class + '.is-loading', { + hidden: true, + } ); + + expect( isRefreshed ).not.toBeCalled(); + + await page.waitForSelector( selectors.frontend.filter ); + await page.click( selectors.frontend.filter ); + await Promise.all( [ + page.waitForNavigation( { + waitUntil: 'networkidle0', + } ), + page.click( selectors.frontend.submitButton ), + ] ); + + const pageURL = page.url(); + const parsedURL = new URL( pageURL ); + + await page.waitForSelector( + selectors.frontend.classicProductsList + ); + const products = await page.$$( + selectors.frontend.classicProductsList + ); + + expect( isRefreshed ).toBeCalledTimes( 1 ); + expect( products ).toHaveLength( 1 ); + await expect( page ).toMatch( block.foundProduct ); + expect( parsedURL.search ).toEqual( + block.urlSearchParamWhenFilterIsApplied + ); + } ); + } ); +} ); diff --git a/plugins/woocommerce-blocks/tests/e2e/specs/shopper/mini-cart.test.js b/plugins/woocommerce-blocks/tests/e2e/specs/shopper/mini-cart.test.js index f8c880ebcb8..4ac221c0073 100644 --- a/plugins/woocommerce-blocks/tests/e2e/specs/shopper/mini-cart.test.js +++ b/plugins/woocommerce-blocks/tests/e2e/specs/shopper/mini-cart.test.js @@ -19,8 +19,21 @@ import { useTheme } from '../../utils'; const block = { name: 'Mini Cart', + selectors: { + frontend: { + productWithAddToCartButton: + '.wc-block-grid__product:nth-child(2) .add_to_cart_button', + productTitle: + '.wc-block-grid__product:nth-child(2) .wc-block-components-product-name', + productPrice: + '.wc-block-grid__product:nth-child(2) .wc-block-grid__product-price', + addToCartButton: 'button.add_to_cart_button', + }, + }, }; +const { selectors } = block; + const options = getDefaultOptions(); const clickMiniCartButton = async () => { @@ -196,9 +209,7 @@ describe( 'Shopper → Mini Cart', () => { } ); it( 'The Mini Cart title shows correct amount', async () => { - await page.click( - '.wc-block-grid__product:first-child .add_to_cart_button' - ); + await page.click( selectors.frontend.productWithAddToCartButton ); await expect( page ).toMatchElement( '.wc-block-mini-cart__title', { text: 'Your cart (1 item)', @@ -226,9 +237,7 @@ describe( 'Shopper → Mini Cart', () => { ); } - // Get a random product to better replicate human behavior. - const product = - products[ Math.floor( Math.random() * products.length ) ]; + const product = products[ 1 ]; const [ productTitle ] = await getTextContent( '.wc-block-components-product-name', product @@ -246,7 +255,7 @@ describe( 'Shopper → Mini Cart', () => { } ); it( 'Filled Mini Cart footer contains subtotal, view cart button, and go to checkout buttons', async () => { - await page.click( '.add_to_cart_button' ); + await page.click( selectors.frontend.addToCartButton ); await expect( page ).toMatchElement( '.wc-block-mini-cart__title', { text: 'Your cart', @@ -285,9 +294,7 @@ describe( 'Shopper → Mini Cart', () => { } ); it( 'The quantity of a product can be updated using plus and minus button', async () => { - await page.click( - '.wc-block-grid__product:first-child .add_to_cart_button' - ); + await page.click( selectors.frontend.productWithAddToCartButton ); await expect( page ).toMatchElement( '.wc-block-mini-cart__title', { text: 'Your cart (1 item)', @@ -331,9 +338,7 @@ describe( 'Shopper → Mini Cart', () => { } ); it( 'Minus button is disabled if product quantity is 1', async () => { - await page.click( - '.wc-block-grid__product:first-child .add_to_cart_button' - ); + await page.click( selectors.frontend.productWithAddToCartButton ); await expect( page ).toMatchElement( '.wc-block-mini-cart__title', { text: 'Your cart (1 item)', @@ -425,12 +430,10 @@ describe( 'Shopper → Mini Cart', () => { it( 'Mini Cart show tax label and price including tax', async () => { const [ priceInLoop ] = await getTextContent( - '.wc-block-grid__product:first-child .wc-block-grid__product-price' + selectors.frontend.productPrice ); - await page.click( - '.wc-block-grid__product:first-child .add_to_cart_button' - ); + await page.click( selectors.frontend.productWithAddToCartButton ); await expect( page ).toMatchElement( '.wc-block-mini-cart__title', { text: 'Your cart (1 item)', @@ -471,7 +474,7 @@ describe( 'Shopper → Mini Cart', () => { } ); it( 'Can remove product from Mini Cart', async () => { - await page.click( '.add_to_cart_button' ); + await page.click( selectors.frontend.addToCartButton ); await expect( page ).toMatchElement( '.wc-block-mini-cart__title', { text: 'Your cart (1 item)', @@ -497,12 +500,10 @@ describe( 'Shopper → Mini Cart', () => { it( 'Can go to cart page from the Mini Cart Footer', async () => { const [ productTitle ] = await getTextContent( - '.wc-block-grid__product:first-child .wc-block-components-product-name' + selectors.frontend.productTitle ); - await page.click( - '.wc-block-grid__product:first-child .add_to_cart_button' - ); + await page.click( selectors.frontend.productWithAddToCartButton ); await expect( page ).toMatchElement( '.wc-block-mini-cart__products-table', @@ -533,13 +534,11 @@ describe( 'Shopper → Mini Cart', () => { it( 'Can go to checkout page from the Mini Cart Footer', async () => { const productTitle = await page.$eval( - '.wc-block-grid__product:first-child .wc-block-components-product-name', + selectors.frontend.productTitle, ( el ) => el.textContent ); - await page.click( - '.wc-block-grid__product:first-child .add_to_cart_button' - ); + await page.click( selectors.frontend.productWithAddToCartButton ); await expect( page ).toMatchElement( '.wc-block-mini-cart__products-table', @@ -591,7 +590,7 @@ describe( 'Shopper → Mini Cart', () => { it( 'User can see translation in filled Mini Cart', async () => { await page.click( - '.wc-block-grid__product:first-child .add_to_cart_button' + selectors.frontend.productWithAddToCartButton ); await expect( page ).toMatchElement( @@ -623,7 +622,7 @@ describe( 'Shopper → Mini Cart', () => { it( 'User can see translation in filled Mini Cart', async () => { await page.click( - '.wc-block-grid__product:first-child .add_to_cart_button' + selectors.frontend.productWithAddToCartButton ); await expect( page ).toMatchElement(