Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Show decimals in mini cart regular price would not have decimals #5125

Closed

Conversation

nielslange
Copy link
Member

@nielslange nielslange commented Nov 11, 2021

Fixes #5018 & #5019

Problem

In #5019, @dinhtungdu reported that the decimals in the mini cart block are not visible, when the price is 0. After viewing the unit tests of this fix, I noticed that this problem not only affects a $0 price, but also a price that has no decimals, such as $15.00. This price will then appear as $15 in the mini cart.

Reason

To format the price, we convert the regular price into a decimal price by multiplying the regular price with 10 to the power of the number of decimals. Let's say the merchant sets the number of decimals to 2 and the cart contains products with a value of $23.05. We'd then convert the regular price to a decimal price as follows:

23.05 * 10 ^ 2 = 2305

Now, let's take a look what happens when we convert a $0 price:

0 * 10 ^ 2 = 0

To keep the decimal zeros, we'd expect the decimal price 000, but we get the decimal price 0.

Let's also take a quick look what happens when we convert a $15 price:

15.00 * 10 ^ 2 = 1500

So far, this is ok. However, when formatting the price in https://github.com/woocommerce/woocommerce-gutenberg-products-block/blob/6cb995c49f11ee59f03951a57ab8a93b6de01753/packages/prices/utils/price.ts#L137, the decimals get lost:

1500 / 10 ^ 2 = 15

Solution

To solve this problem, I'm splitting the price into an integer and a decimal part. That way, I can ensure that the decimals do not get lost independent if the cart holds a $0 price or a higher price, but without decimals, e.g. $15.

Testing

Automated testing

  1. Run the following command in the terminal:
npm run test -i packages/prices/utils/test/price.js

Manual testing

Test $0.00 value
  1. Go to WP Admin » WooCommerce » Setting » General » Currency options.
  2. Set the number of decimals to 2.
  3. Create a test page with the mini cart block and save it.
  4. Open the mini cart in the frontend.
  5. See that the initial price shows as $0.00.
  6. Hover over the price and see that it remains $0.00.

Test number of decimals
  1. Go to WP Admin » WooCommerce » Setting » General » Currency options.
  2. Set the number of decimals to 3.
  3. Open the mini cart in the frontend.
  4. See that the initial price shows as $0.000.
  5. Hover over the price and see that it remains $0.000.

Test separators
  1. Go to WP Admin » WooCommerce » Setting » General » Currency options.
  2. Set the thousand separator to . and the decimal separator to ,.
  3. Go to the frontend and add a product to the cart.
  4. Increase the order quantity so that the price is above $1.000.
  5. See that the thousand separator as . and the decimal separator as ,.
  6. Hover over the price and see that the thousand separator and the decimal separator remain the same.

Test currency and currency position
  1. Go to WP Admin » WooCommerce » Setting » General » Currency options.
  2. Set the currency to Euro (€) and the currency position to Right with space.
  3. Go to the frontend and add a product to the cart.
  4. See that the currency is Euro (€) and that it's place on the right-hand side, including a space.
  5. Hover over the price and the currency and the currency position remain the same.

Changelog

Ensure that formated price shows the expected number of decimals, thousand separator and decimal separator.

@nielslange nielslange added status: needs review type: bug The issue/PR concerns a confirmed bug. block: mini-cart Issues related to the Mini-Cart block. labels Nov 11, 2021
@rubikuserbot rubikuserbot requested review from a team and opr and removed request for a team November 11, 2021 06:21
@github-actions
Copy link
Contributor

github-actions bot commented Nov 11, 2021

Size Change: +153 B (0%)

Total Size: 1.12 MB

Filename Size Change
build/blocks-checkout.js 21.3 kB -2 B (0%)
build/price-format.js 1.55 kB +156 B (+11%) ⚠️
build/wc-blocks-registry.js 3.71 kB -1 B (0%)
ℹ️ View Unchanged
Filename Size
build/active-filters-frontend.js 8.24 kB
build/active-filters.js 8 kB
build/all-products-frontend.js 23.5 kB
build/all-products.js 38.3 kB
build/all-reviews.js 9.56 kB
build/atomic-block-components/add-to-cart--atomic-block-components/button--atomic-block-components/image---a7e2bb9b.js 3.2 kB
build/atomic-block-components/add-to-cart--atomic-block-components/button.js 1.81 kB
build/atomic-block-components/add-to-cart-frontend.js 8.34 kB
build/atomic-block-components/add-to-cart.js 7.85 kB
build/atomic-block-components/button-frontend.js 1.74 kB
build/atomic-block-components/button.js 876 B
build/atomic-block-components/category-list-frontend.js 466 B
build/atomic-block-components/category-list.js 469 B
build/atomic-block-components/image-frontend.js 1.71 kB
build/atomic-block-components/image.js 1.36 kB
build/atomic-block-components/price-frontend.js 2.13 kB
build/atomic-block-components/price.js 2.11 kB
build/atomic-block-components/rating-frontend.js 562 B
build/atomic-block-components/rating.js 566 B
build/atomic-block-components/sale-badge-frontend.js 861 B
build/atomic-block-components/sale-badge.js 868 B
build/atomic-block-components/sku-frontend.js 390 B
build/atomic-block-components/sku.js 393 B
build/atomic-block-components/stock-indicator-frontend.js 611 B
build/atomic-block-components/stock-indicator.js 610 B
build/atomic-block-components/summary-frontend.js 907 B
build/atomic-block-components/summary.js 911 B
build/atomic-block-components/tag-list-frontend.js 468 B
build/atomic-block-components/tag-list.js 471 B
build/atomic-block-components/title-frontend.js 1.47 kB
build/atomic-block-components/title.js 1.47 kB
build/attribute-filter-frontend.js 18.2 kB
build/attribute-filter.js 12.1 kB
build/cart-blocks/accepted-payment-methods-frontend.js 1.39 kB
build/cart-blocks/checkout-button-frontend.js 1.21 kB
build/cart-blocks/empty-cart-frontend.js 348 B
build/cart-blocks/express-payment--checkout-blocks/express-payment--checkout-blocks/payment-frontend.js 4.74 kB
build/cart-blocks/express-payment-frontend.js 1.59 kB
build/cart-blocks/filled-cart-frontend.js 805 B
build/cart-blocks/items-frontend.js 302 B
build/cart-blocks/line-items-frontend.js 5.87 kB
build/cart-blocks/order-summary--checkout-blocks/billing-address--checkout-blocks/shipping-address-frontend.js 3.69 kB
build/cart-blocks/order-summary-frontend.js 7.4 kB
build/cart-blocks/totals-frontend.js 324 B
build/cart-frontend.js 52.6 kB
build/cart.js 50.7 kB
build/checkout-blocks/actions-frontend.js 1.48 kB
build/checkout-blocks/billing-address-frontend.js 2.64 kB
build/checkout-blocks/contact-information-frontend.js 3.62 kB
build/checkout-blocks/express-payment-frontend.js 1.93 kB
build/checkout-blocks/fields-frontend.js 348 B
build/checkout-blocks/order-note-frontend.js 1.25 kB
build/checkout-blocks/order-summary-frontend.js 12.9 kB
build/checkout-blocks/payment-frontend.js 4.47 kB
build/checkout-blocks/shipping-address-frontend.js 2.72 kB
build/checkout-blocks/shipping-methods-frontend.js 5.54 kB
build/checkout-blocks/terms-frontend.js 1.29 kB
build/checkout-blocks/totals-frontend.js 329 B
build/checkout-frontend.js 54.9 kB
build/checkout.js 54 kB
build/featured-category.js 7.74 kB
build/featured-product.js 9.43 kB
build/handpicked-products.js 6.27 kB
build/legacy-template.js 2.05 kB
build/mini-cart-component-frontend.js 44.8 kB
build/mini-cart-contents.js 2.35 kB
build/mini-cart-frontend.js 2.34 kB
build/mini-cart.js 6.24 kB
build/price-filter-frontend.js 14.2 kB
build/price-filter.js 9.65 kB
build/product-best-sellers.js 6.62 kB
build/product-categories.js 3.38 kB
build/product-category.js 7.48 kB
build/product-new.js 6.77 kB
build/product-on-sale.js 7.12 kB
build/product-search.js 2.7 kB
build/product-tag.js 6.6 kB
build/product-top-rated.js 6.74 kB
build/products-by-attribute.js 7.71 kB
build/reviews-by-category.js 11.5 kB
build/reviews-by-product.js 13 kB
build/reviews-frontend.js 9.03 kB
build/single-product-frontend.js 26.9 kB
build/single-product.js 10 kB
build/stock-filter-frontend.js 8.68 kB
build/stock-filter.js 7.81 kB
build/vendors--atomic-block-components/add-to-cart--cart-blocks/order-summary--checkout-blocks/billing-ad--c5eb4dcd-frontend.js 16.1 kB
build/vendors--atomic-block-components/add-to-cart-frontend.js 4.77 kB
build/vendors--atomic-block-components/price--cart-blocks/line-items--cart-blocks/order-summary--checkout--8a3571de-frontend.js 5.71 kB
build/vendors--cart-blocks/line-items--checkout-blocks/order-summary-frontend.js 3.14 kB
build/vendors--cart-blocks/order-summary--checkout-blocks/billing-address--checkout-blocks/order-summary---eb4d2cec-frontend.js 5.03 kB
build/wc-blocks-data.js 11.3 kB
build/wc-blocks-editor-style-rtl.css 15.8 kB
build/wc-blocks-editor-style.css 15.8 kB
build/wc-blocks-google-analytics.js 1.98 kB
build/wc-blocks-middleware.js 1.19 kB
build/wc-blocks-shared-context.js 1.54 kB
build/wc-blocks-shared-hocs.js 1.92 kB
build/wc-blocks-style-rtl.css 21.1 kB
build/wc-blocks-style.css 21.1 kB
build/wc-blocks-vendors-style-rtl.css 1.37 kB
build/wc-blocks-vendors-style.css 1.37 kB
build/wc-blocks-vendors.js 255 kB
build/wc-blocks.js 3.49 kB
build/wc-payment-method-bacs.js 806 B
build/wc-payment-method-cheque.js 806 B
build/wc-payment-method-cod.js 898 B
build/wc-payment-method-paypal.js 839 B
build/wc-payment-method-stripe.js 12.2 kB
build/wc-settings.js 2.91 kB

compressed-size-action

@nielslange nielslange marked this pull request as draft November 11, 2021 07:30
@nielslange nielslange changed the title Show decimals in mini cart even when price is 0 Show decimals in mini cart regular price would not have decimals Nov 11, 2021
@nielslange nielslange marked this pull request as ready for review November 15, 2021 03:58
Copy link
Contributor

@opr opr left a comment

Choose a reason for hiding this comment

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

Works well for me, cool use of regex and I love the tests you added 👍🏼

Besides what Tung has already mentioned, I've added a couple of comments relating to the documentation of functions, but these are only minor edits so I'll approve.

Please reconsider the testing instructions, I don't think there's any value getting people to experience the bug in trunk first before testing. Especially not for user-facing testing.

packages/prices/utils/price.ts Outdated Show resolved Hide resolved
packages/prices/utils/price.ts Outdated Show resolved Hide resolved
@mikejolley
Copy link
Member

@nielslange I only just noticed this PR and wanted to note that these issues were very similar:

#5018
#5019

I fixed the formatting in #5188

This is going to impact this PR. I also needed to separate the before/after decimal part and implemented a splitDecimal function based on react-number-format which is a package we use elsewhere. Might be worth a look?

@Aljullu Aljullu removed this from the 6.4.0 milestone Nov 22, 2021
@Aljullu Aljullu added this to the 6.5.0 milestone Nov 22, 2021
@nielslange
Copy link
Member Author

@nielslange I only just noticed this PR and wanted to note that these issues were very similar:

#5018 #5019

I fixed the formatting in #5188

Thanks for letting me know, @mikejolley. I just checked #5188 and noticed that it would break this PR, which is pretty much done. As this PR fixes both #5018 and #5019, I reverted your changes for now.

This is going to impact this PR. I also needed to separate the before/after decimal part and implemented a splitDecimal function based on react-number-format which is a package we use elsewhere. Might be worth a look?

In p1636638621033700/1636637781.030600-slack-C8X6Q7XQU, @senadir mentioned that react-number-format should be replaced in the future. That was one of the reasons, why I spin up this PR. I should have mentioned though that this PR not only fixes #5018, but also #5019. That was my bad.

@nielslange
Copy link
Member Author

nielslange commented Nov 23, 2021

Please reconsider the testing instructions, I don't think there's any value getting people to experience the bug in trunk first before testing. Especially not for user-facing testing.

I'll adjust the testing instructions accordingly, @opr.


@dinhtungdu & @opr Do you two want to do a last review of this PR, or shall I go ahead and merge it?

Copy link
Contributor

@opr opr left a comment

Choose a reason for hiding this comment

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

From my point of view it works and the code looks fine, so I can approve! I would like to cc @mikejolley since this affects work you did (Niels has reverted one of your PRs) please can you check over it too?

@mikejolley
Copy link
Member

@senadir mentioned that react-number-format should be replaced in the future. That was one of the reasons, why I spin up this PR.

I did not use react-number-format as an import, I copied the approach/function used to split the first and last part of the decimal (splitDecimal) which resulted in much less code that the splitting you original went with.

I think you've also reverted a fix where I added:

if ( ! currencyData?.currency_code ) {

I found that on the first load, currencyData can be empty (default state) with no currency_code which results in a flash of the wrong price. I tested this using console logs and noted the prices were not formatted correctly on first render. If you console.log the currencyData at that point you can see for yourself.

${ '' } | ${ '' }
${ null } | ${ '' }
${ undefined } | ${ '' }
`(
'correctly formats price given "$value" only as "$expected"',
Copy link
Member

Choose a reason for hiding this comment

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

Having $expected was useful when viewing the output of the tests.

@@ -76,7 +76,7 @@ export const getCurrencyFromPriceResponse = (
| Record< string, never >
| CartShippingPackageShippingRate
): Currency => {
if ( ! currencyData?.currency_code ) {
Copy link
Member

Choose a reason for hiding this comment

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

This prevents invalid (default state) currencyData taking precedence over the default siteCurrencySettings.

* @param {number} minorUnit The number of decimals to display.
* @return {string} The extracted decimal value.
*/
export const getDecimalValue = (
Copy link
Member

Choose a reason for hiding this comment

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

These functions seem to be parsing the decimal value, and formatting it, is that correct? The splitDecimal I added seemed more easy to understand. Can we not do the formatting part (adding 0's etc) later using a separate function? cc @senadir

@nielslange
Copy link
Member Author

Closing this PR in benefit of #5219.

@nielslange nielslange closed this Nov 23, 2021
@nielslange nielslange removed this from the 6.5.0 milestone Nov 23, 2021
@nielslange nielslange deleted the fix/5019-show-decimals-in-mini-cart-for-0-price branch December 13, 2021 05:44
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
block: mini-cart Issues related to the Mini-Cart block. type: bug The issue/PR concerns a confirmed bug.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

formatPrice doesn't work with custom decimal separator
5 participants