* Create Cross-Sells product list

* Show “Read more” button for out-of-stock cross-sells products

* Update assets/js/blocks/cart/inner-blocks/cart-cross-sells-products/block.tsx

Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com>

* Update assets/js/blocks/cart/cart-cross-sells-product-list/index.tsx

Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com>

* Remove obsolete isLoading and placeholderRows

* Fix TS errors

* Rename crossSellsProduct to product

* Fix critical error

* Create 2e2 tests for Cross-Sells block

Co-authored-by: Thomas Roberts <5656702+opr@users.noreply.github.com>
This commit is contained in:
Niels Lange 2022-09-21 13:29:16 +07:00 committed by GitHub
parent 3d55668983
commit 77a2255978
7 changed files with 75 additions and 5 deletions

View File

@ -1,2 +1,3 @@
*.json
*.scss *.scss
*.yml *.yml

View File

@ -53,8 +53,8 @@
"lint:js:report": "npm run lint:js -- --output-file eslint_report.json --ext=js,ts,tsx --format json", "lint:js:report": "npm run lint:js -- --output-file eslint_report.json --ext=js,ts,tsx --format json",
"lint:js-fix": "eslint assets/js --ext=js,jsx,ts,tsx --fix", "lint:js-fix": "eslint assets/js --ext=js,jsx,ts,tsx --fix",
"lint:md:docs": "wp-scripts lint-md-docs", "lint:md:docs": "wp-scripts lint-md-docs",
"lint:php": "composer run-script phpcs ./src", "lint:php": "composer run-script phpcs ./src && composer run-script phpcs ./tests/mocks/woo-test-helper",
"lint:php-fix": "composer run-script phpcbf ./src", "lint:php-fix": "composer run-script phpcbf ./src && composer run-script phpcbf ./tests/mocks/woo-test-helper",
"package-plugin": "rimraf woocommerce-gutenberg-products-block.zip && ./bin/build-plugin-zip.sh", "package-plugin": "rimraf woocommerce-gutenberg-products-block.zip && ./bin/build-plugin-zip.sh",
"package-plugin:dev": "rimraf woocommerce-gutenberg-products-block.zip && ./bin/build-plugin-zip.sh -d", "package-plugin:dev": "rimraf woocommerce-gutenberg-products-block.zip && ./bin/build-plugin-zip.sh -d",
"package-plugin:zip-only": "rimraf woocommerce-gutenberg-products-block.zip && ./bin/build-plugin-zip.sh -z", "package-plugin:zip-only": "rimraf woocommerce-gutenberg-products-block.zip && ./bin/build-plugin-zip.sh -z",

File diff suppressed because one or more lines are too long

View File

@ -43,6 +43,12 @@ const emptyCartBlock = {
class: '.wp-block-woocommerce-empty-cart-block', class: '.wp-block-woocommerce-empty-cart-block',
}; };
const crossSellsBlock = {
name: 'Cart Cross-Sells block',
slug: 'woocommerce/cart-cross-sells-products-block',
class: '.wp-block-woocommerce-cart-cross-sells-products-block',
};
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) { if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) {
// eslint-disable-next-line jest/no-focused-tests, jest/expect-expect // eslint-disable-next-line jest/no-focused-tests, jest/expect-expect
test.only( `skipping ${ block.name } tests`, () => {} ); test.only( `skipping ${ block.name } tests`, () => {} );
@ -63,6 +69,7 @@ describe( `${ block.name } Block`, () => {
it( 'renders without crashing', async () => { it( 'renders without crashing', async () => {
await expect( page ).toRenderBlock( block ); await expect( page ).toRenderBlock( block );
await expect( page ).toRenderBlock( filledCartBlock ); await expect( page ).toRenderBlock( filledCartBlock );
await expect( page ).toRenderBlock( crossSellsBlock );
await expect( page ).toRenderBlock( emptyCartBlock ); await expect( page ).toRenderBlock( emptyCartBlock );
} ); } );

View File

@ -1,7 +1,12 @@
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { shopper, SIMPLE_VIRTUAL_PRODUCT_NAME } from '../../../../utils'; import {
shopper,
SIMPLE_VIRTUAL_PRODUCT_NAME,
SIMPLE_PHYSICAL_PRODUCT_NAME,
} from '../../../../utils';
import { BASE_URL } from '../../../../utils/constants';
if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) { if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) {
// Skips all the tests if it's a WooCommerce Core process environment. // Skips all the tests if it's a WooCommerce Core process environment.
@ -11,6 +16,9 @@ if ( process.env.WOOCOMMERCE_BLOCKS_PHASE < 2 ) {
describe( 'Shopper → Cart', () => { describe( 'Shopper → Cart', () => {
beforeAll( async () => { beforeAll( async () => {
await page.goto( `${ BASE_URL }/?setup_cross_sells` );
// eslint-disable-next-line jest/no-standalone-expect
await expect( page ).toMatch( 'Cross-Sells products set up.' );
await shopper.block.emptyCart(); await shopper.block.emptyCart();
} ); } );
@ -97,6 +105,22 @@ describe( 'Shopper → Cart', () => {
await shopper.block.productIsInCart( SIMPLE_VIRTUAL_PRODUCT_NAME, 4 ); await shopper.block.productIsInCart( SIMPLE_VIRTUAL_PRODUCT_NAME, 4 );
} ); } );
it( 'User can see Cross-Sells products block', async () => {
await shopper.block.emptyCart();
await shopper.goToShop();
await shopper.addToCartFromShopPage( SIMPLE_PHYSICAL_PRODUCT_NAME );
await shopper.block.goToCart();
await expect( page ).toMatchElement(
'.wp-block-woocommerce-cart-cross-sells-block'
);
await shopper.block.addCrossSellsProductToCart();
// To avoid flakiness: Wait until the cart contains two entries.
await page.waitForSelector(
'.wp-block-woocommerce-cart-line-items-block tr:nth-child(2)'
);
await shopper.block.productIsInCart( '32GB USB Stick', 1 );
} );
it( 'User can proceed to checkout', async () => { it( 'User can proceed to checkout', async () => {
await shopper.goToShop(); await shopper.goToShop();
await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME ); await shopper.addToCartFromShopPage( SIMPLE_VIRTUAL_PRODUCT_NAME );

View File

@ -28,7 +28,7 @@ function woocommerce_setup_terms_and_privacy_page() {
exit( 'Terms & Privacy pages set up.' ); exit( 'Terms & Privacy pages set up.' );
} }
// phpcs:disable WordPress.Security.NonceVerification.Recommended // phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( isset( $_GET['teardown_terms_and_privacy'] ) ) { if ( isset( $_GET['teardown_terms_and_privacy'] ) ) {
unpublish_privacy_page(); unpublish_privacy_page();
delete_terms_page(); delete_terms_page();
@ -94,3 +94,32 @@ function delete_terms_page() {
$data = array( 'post_title' => 'Terms & Conditions' ); $data = array( 'post_title' => 'Terms & Conditions' );
$wpdb->delete( $table, $data ); $wpdb->delete( $table, $data );
} }
/**
* Define URL endpoint for setting up cross-sells products.
*/
function woocommerce_setup_cross_sells_products() {
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( isset( $_GET['setup_cross_sells'] ) ) {
setup_cross_sells();
exit( 'Cross-Sells products set up.' );
}
}
add_action( 'init', 'woocommerce_setup_cross_sells_products' );
/**
* Set up Cross-Sells products.
*/
function setup_cross_sells() {
global $wpdb;
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
$select = "SELECT * FROM {$wpdb->prefix}posts WHERE post_title = '128GB USB Stick' AND post_status = 'publish' AND post_type = 'product'";
$id_product = $wpdb->get_row( $select );
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
$select = "SELECT * FROM {$wpdb->prefix}posts WHERE post_title = '32GB USB Stick' AND post_status = 'publish' AND post_type = 'product'";
$id_cross_sell = $wpdb->get_row( $select );
add_post_meta( $id_product->ID, '_crosssell_ids', $id_cross_sell->ID );
}

View File

@ -311,6 +311,15 @@ export const shopper = {
] ); ] );
}, },
addCrossSellsProductToCart: async () => {
await page.waitForSelector(
'.wc-block-components-product-add-to-cart-button'
);
expect( page ).toClick(
'.wc-block-components-product-add-to-cart-button'
);
},
selectAndVerifyShippingOption: async ( selectAndVerifyShippingOption: async (
shippingName, shippingName,
shippingPrice shippingPrice