Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix incorrect quantity when product is already in cart #421

Merged
merged 4 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions assets/js/src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ const formatCategoryKey = ( index ) => {
*/
export const getProductFromID = ( search, products, cart ) => {
return (
cart?.items?.find( ( { id } ) => id === search ) ??
products?.find( ( { id } ) => id === search )
products?.find( ( { id } ) => id === search ) ??
cart?.items?.find( ( { id } ) => id === search )
);
};
9 changes: 7 additions & 2 deletions includes/class-wc-abstract-google-analytics-js.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function () {
add_action(
'woocommerce_add_to_cart',
function ( $cart_item_key, $product_id, $quantity, $variation_id, $variation ) {
$this->set_script_data( 'added_to_cart', $this->get_formatted_product( wc_get_product( $product_id ), $variation_id, $variation ) );
$this->set_script_data( 'added_to_cart', $this->get_formatted_product( wc_get_product( $product_id ), $variation_id, $variation, $quantity ) );
},
10,
5
Expand Down Expand Up @@ -208,10 +208,11 @@ function ( $item ) {
* @param int $variation_id Variation product ID.
* @param array|bool $variation An array containing product variation attributes to include in the product data.
* For the "variation" type products, we'll use product->get_attributes.
* @param bool|int $quantity Quantity to include in the formatted product object
*
* @return array
*/
public function get_formatted_product( WC_Product $product, $variation_id = 0, $variation = false ): array {
public function get_formatted_product( WC_Product $product, $variation_id = 0, $variation = false, $quantity = false ): array {
$product_id = $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id();
$price = $product->get_price();

Expand Down Expand Up @@ -241,6 +242,10 @@ public function get_formatted_product( WC_Product $product, $variation_id = 0, $
),
);

if ( $quantity ) {
$formatted['quantity'] = (int) $quantity;
}

if ( $product->is_type( 'variation' ) ) {
$variation = $product->get_attributes();
}
Expand Down
35 changes: 35 additions & 0 deletions tests/e2e/specs/gtag-events/blocks-pages.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,41 @@ test.describe( 'GTag events on block pages', () => {
} );
} );

test( 'Add to cart has correct quantity when product is already in cart', async ( {
page,
} ) => {
const addToCart = `[data-product_id="${ simpleProductID }"]`;

await createProductsBlockShopPage();
await page.goto( `products-block-shop` );

const addToCartButton = await page.locator( addToCart ).first();

await addToCartButton.click();
await expect( addToCartButton.getByText( '1 in cart' ) ).toBeVisible();
await addToCartButton.click();
await expect( addToCartButton.getByText( '2 in cart' ) ).toBeVisible();

await page.reload();

const event = trackGtagEvent( page, 'add_to_cart' );

const addToCartButton2 = await page.locator( addToCart ).first();
await addToCartButton2.click();
await expect( addToCartButton.getByText( '3 in cart' ) ).toBeVisible();

await event.then( ( request ) => {
const data = getEventData( request, 'add_to_cart' );
expect( data.product1 ).toEqual( {
id: simpleProductID.toString(),
nm: 'Simple product',
ca: 'Uncategorized',
qt: '1',
pr: simpleProductPrice.toString(),
} );
} );
} );

test( 'View item list event is sent from the products block shop page', async ( {
page,
} ) => {
Expand Down
26 changes: 26 additions & 0 deletions tests/e2e/specs/gtag-events/classic-pages.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,32 @@ test.describe( 'GTag events on classic pages', () => {
} );
} );

test( 'Add to cart quantity is sent on a single product page', async ( {
page,
} ) => {
const event = trackGtagEvent( page, 'add_to_cart' );

await page.goto( `?p=${ simpleProductID }` );

await page.locator( '.quantity input.qty' ).first().fill( '3' );

const addToCart = `.single_add_to_cart_button[value="${ simpleProductID }"]`;
const addToCartButton = await page.locator( addToCart ).first();

await addToCartButton.click();
Copy link
Member

Choose a reason for hiding this comment

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

❔ What do you think adding a page.reload() for the classic shop as well so it would match the testing instruction in the PR description?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the review @ianlin 🙌

The error with the product quantity on the single page wasn't triggered with a page reload in the same way the other one was. When the added_to_cart hook runs the quantity wasn't being added to the product object so for the test we just need to click the Add to cart button and then confirm the quantity is now present in the event. Apologies if that wasn't clear from the testing instructions.


await event.then( ( request ) => {
const data = getEventData( request, 'add_to_cart' );
expect( data.product1 ).toEqual( {
id: simpleProductID.toString(),
nm: 'Simple product',
ca: 'Uncategorized',
qt: '3',
pr: simpleProductPrice.toString(),
} );
} );
} );

test( 'Add to cart event is sent on the home page when adding product through URL', async ( {
page,
} ) => {
Expand Down
Loading