Merge pull request woocommerce/woocommerce-admin#122 from woocommerce/add/format-currency
Add function to format price by currency, and update string & decimal parsing functions
This commit is contained in:
commit
d278735434
|
@ -11,7 +11,7 @@ import PropTypes from 'prop-types';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import ActivityCard from 'components/activity-card';
|
||||
import { getCurrencyFormatDecimal, getCurrencyFormatString } from 'lib/currency';
|
||||
import { formatCurrency, getCurrencyFormatDecimal } from 'lib/currency';
|
||||
import { getOrderRefundTotal } from 'lib/order-values';
|
||||
import { Section } from 'layout/section';
|
||||
|
||||
|
@ -53,11 +53,11 @@ function OrdersList( { orders } ) {
|
|||
</span>{' '}
|
||||
{ refundValue ? (
|
||||
<span>
|
||||
<s>{ getCurrencyFormatString( total ) }</s>{' '}
|
||||
{ getCurrencyFormatString( remainingTotal ) }
|
||||
<s>{ formatCurrency( total, order.currency ) }</s>{' '}
|
||||
{ formatCurrency( remainingTotal, order.currency ) }
|
||||
</span>
|
||||
) : (
|
||||
<span>{ getCurrencyFormatString( total ) }</span>
|
||||
<span>{ formatCurrency( total, order.currency ) }</span>
|
||||
) }
|
||||
</div>
|
||||
</ActivityCard>
|
||||
|
|
|
@ -1,17 +1,37 @@
|
|||
/** @format */
|
||||
/**
|
||||
* NOTE This is a placeholder library until we figure out currency formatting for real.
|
||||
* External dependencies
|
||||
*/
|
||||
import { isNaN } from 'lodash';
|
||||
|
||||
/**
|
||||
* Get the rounded decimal value of a number at the precision used for a given currency.
|
||||
* Formats money with a given currency code. Uses site's current locale for symbol formatting
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat
|
||||
* @param {Number|String} number number to format
|
||||
* @param {String} currency currency code e.g. 'USD'
|
||||
* @returns {?String} A formatted string.
|
||||
*/
|
||||
export function formatCurrency( number, currency ) {
|
||||
const locale = wcSettings.locale || 'en-US'; // Default so we don't break.
|
||||
if ( 'number' !== typeof number ) {
|
||||
number = parseFloat( number );
|
||||
}
|
||||
if ( isNaN( number ) ) {
|
||||
return '';
|
||||
}
|
||||
return new Intl.NumberFormat( locale, { style: 'currency', currency } ).format( number );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rounded decimal value of a number at the precision used for the current currency.
|
||||
* This is a work-around for fraction-cents, meant to be used like `wc_format_decimal`
|
||||
*
|
||||
* @param {Number|String} number A floating point number (or integer), or string that converts to a number
|
||||
* @return {Number} The original number rounded to a decimal point
|
||||
*/
|
||||
export function getCurrencyFormatDecimal( number, /* currency = 'USD' */ ) {
|
||||
const precision = 2; // this would depend on currency
|
||||
export function getCurrencyFormatDecimal( number ) {
|
||||
const { precision = 2 } = wcSettings.currency;
|
||||
if ( 'number' !== typeof number ) {
|
||||
number = parseFloat( number );
|
||||
}
|
||||
|
@ -22,14 +42,14 @@ export function getCurrencyFormatDecimal( number, /* currency = 'USD' */ ) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the string representation of a floating point number to the precision used by a given currency.
|
||||
* Get the string representation of a floating point number to the precision used by the current currency.
|
||||
* This is different from `formatCurrency` by not returning the currency symbol.
|
||||
*
|
||||
* @param {Number|String} number A floating point number (or integer), or string that converts to a number
|
||||
* @return {String} The original number rounded to a decimal point
|
||||
*/
|
||||
export function getCurrencyFormatString( number, /* currency = 'USD' */ ) {
|
||||
const precision = 2; // this would depend on currency
|
||||
export function getCurrencyFormatString( number ) {
|
||||
const { precision = 2 } = wcSettings.currency;
|
||||
if ( 'number' !== typeof number ) {
|
||||
number = parseFloat( number );
|
||||
}
|
||||
|
|
|
@ -2,66 +2,100 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getCurrencyFormatDecimal, getCurrencyFormatString } from '../index';
|
||||
import { formatCurrency, getCurrencyFormatDecimal, getCurrencyFormatString } from '../index';
|
||||
|
||||
describe( 'formatCurrency', () => {
|
||||
it( 'should round a number to 2 decimal places in USD', () => {
|
||||
expect( formatCurrency( 9.49258, 'USD' ) ).toBe( '$9.49' );
|
||||
expect( formatCurrency( 30, 'USD' ) ).toBe( '$30.00' );
|
||||
expect( formatCurrency( 3.0002, 'USD' ) ).toBe( '$3.00' );
|
||||
} );
|
||||
|
||||
it( 'should round a number to 2 decimal places in GBP', () => {
|
||||
expect( formatCurrency( 8.9272, 'GBP' ) ).toBe( '£8.93' );
|
||||
expect( formatCurrency( 11, 'GBP' ) ).toBe( '£11.00' );
|
||||
expect( formatCurrency( 7.0002, 'GBP' ) ).toBe( '£7.00' );
|
||||
} );
|
||||
|
||||
it( 'should round a number to 0 decimal places in JPY', () => {
|
||||
expect( formatCurrency( 1239.88, 'JPY' ) ).toBe( '¥1,240' );
|
||||
expect( formatCurrency( 1500, 'JPY' ) ).toBe( '¥1,500' );
|
||||
expect( formatCurrency( 33715.02, 'JPY' ) ).toBe( '¥33,715' );
|
||||
} );
|
||||
|
||||
it( 'should correctly convert and round a string', () => {
|
||||
expect( formatCurrency( '19.80', 'USD' ) ).toBe( '$19.80' );
|
||||
} );
|
||||
|
||||
it( "should return empty string when given an input that isn't a number", () => {
|
||||
expect( formatCurrency( 'abc', 'USD' ) ).toBe( '' );
|
||||
expect( formatCurrency( false, 'USD' ) ).toBe( '' );
|
||||
expect( formatCurrency( null, 'USD' ) ).toBe( '' );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'getCurrencyFormatDecimal', () => {
|
||||
it( 'should round a number to 2 decimal places in USD', () => {
|
||||
expect( getCurrencyFormatDecimal( 9.49258, 'USD' ) ).toBe( 9.49 );
|
||||
expect( getCurrencyFormatDecimal( 30, 'USD' ) ).toBe( 30 );
|
||||
expect( getCurrencyFormatDecimal( 3.0002, 'USD' ) ).toBe( 3 );
|
||||
global.wcSettings.currency.precision = 2;
|
||||
expect( getCurrencyFormatDecimal( 9.49258 ) ).toBe( 9.49 );
|
||||
expect( getCurrencyFormatDecimal( 30 ) ).toBe( 30 );
|
||||
expect( getCurrencyFormatDecimal( 3.0002 ) ).toBe( 3 );
|
||||
} );
|
||||
|
||||
// @TODO: Add these tests back once we support multiple currencies
|
||||
// it( 'should round a number to 2 decimal places in GBP', () => {
|
||||
// expect( getCurrencyFormatDecimal( 8.9272, 'GBP' ) ).toBe( 8.93 );
|
||||
// expect( getCurrencyFormatDecimal( 11, 'GBP' ) ).toBe( 11 );
|
||||
// expect( getCurrencyFormatDecimal( 7.0002, 'GBP' ) ).toBe( 7 );
|
||||
// } );
|
||||
|
||||
// it( 'should round a number to 0 decimal places in JPY', () => {
|
||||
// expect( getCurrencyFormatDecimal( 1239.88, 'JPY' ) ).toBe( 1240 );
|
||||
// expect( getCurrencyFormatDecimal( 1500, 'JPY' ) ).toBe( 1500 );
|
||||
// expect( getCurrencyFormatDecimal( 33715.02, 'JPY' ) ).toBe( 33715 );
|
||||
// } );
|
||||
it( 'should round a number to 0 decimal places in JPY', () => {
|
||||
global.wcSettings.currency.precision = 0;
|
||||
expect( getCurrencyFormatDecimal( 1239.88 ) ).toBe( 1240 );
|
||||
expect( getCurrencyFormatDecimal( 1500 ) ).toBe( 1500 );
|
||||
expect( getCurrencyFormatDecimal( 33715.02 ) ).toBe( 33715 );
|
||||
} );
|
||||
|
||||
it( 'should correctly convert and round a string', () => {
|
||||
expect( getCurrencyFormatDecimal( '19.80', 'USD' ) ).toBe( 19.8 );
|
||||
global.wcSettings.currency.precision = 2;
|
||||
expect( getCurrencyFormatDecimal( '19.80' ) ).toBe( 19.8 );
|
||||
} );
|
||||
|
||||
it( 'should default to a precision of 2 if none set', () => {
|
||||
delete global.wcSettings.currency.precision;
|
||||
expect( getCurrencyFormatDecimal( 59.282 ) ).toBe( 59.28 );
|
||||
} );
|
||||
|
||||
it( "should return 0 when given an input that isn't a number", () => {
|
||||
expect( getCurrencyFormatDecimal( 'abc', 'USD' ) ).toBe( 0 );
|
||||
expect( getCurrencyFormatDecimal( false, 'USD' ) ).toBe( 0 );
|
||||
expect( getCurrencyFormatDecimal( null, 'USD' ) ).toBe( 0 );
|
||||
global.wcSettings.currency.precision = 2;
|
||||
expect( getCurrencyFormatDecimal( 'abc' ) ).toBe( 0 );
|
||||
expect( getCurrencyFormatDecimal( false ) ).toBe( 0 );
|
||||
expect( getCurrencyFormatDecimal( null ) ).toBe( 0 );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'getCurrencyFormatString', () => {
|
||||
it( 'should round a number to 2 decimal places in USD', () => {
|
||||
expect( getCurrencyFormatString( 9.49258, 'USD' ) ).toBe( '9.49' );
|
||||
expect( getCurrencyFormatString( 30, 'USD' ) ).toBe( '30.00' );
|
||||
expect( getCurrencyFormatString( 3.0002, 'USD' ) ).toBe( '3.00' );
|
||||
global.wcSettings.currency.precision = 2;
|
||||
expect( getCurrencyFormatString( 9.49258 ) ).toBe( '9.49' );
|
||||
expect( getCurrencyFormatString( 30 ) ).toBe( '30.00' );
|
||||
expect( getCurrencyFormatString( 3.0002 ) ).toBe( '3.00' );
|
||||
} );
|
||||
|
||||
// @TODO: Add these tests back once we support multiple currencies
|
||||
// it( 'should round a number to 2 decimal places in GBP', () => {
|
||||
// expect( getCurrencyFormatString( 8.9272, 'GBP' ) ).toBe( '8.93' );
|
||||
// expect( getCurrencyFormatString( 11, 'GBP' ) ).toBe( '11.00' );
|
||||
// expect( getCurrencyFormatString( 7.0002, 'GBP' ) ).toBe( '7.00' );
|
||||
// } );
|
||||
|
||||
// it( 'should round a number to 0 decimal places in JPY', () => {
|
||||
// expect( getCurrencyFormatString( 1239.88, 'JPY' ) ).toBe( '1240' );
|
||||
// expect( getCurrencyFormatString( 1500, 'JPY' ) ).toBe( '1500' );
|
||||
// expect( getCurrencyFormatString( 33715.02, 'JPY' ) ).toBe( '33715' );
|
||||
// } );
|
||||
it( 'should round a number to 0 decimal places in JPY', () => {
|
||||
global.wcSettings.currency.precision = 0;
|
||||
expect( getCurrencyFormatString( 1239.88 ) ).toBe( '1240' );
|
||||
expect( getCurrencyFormatString( 1500 ) ).toBe( '1500' );
|
||||
expect( getCurrencyFormatString( 33715.02 ) ).toBe( '33715' );
|
||||
} );
|
||||
|
||||
it( 'should correctly convert and round a string', () => {
|
||||
expect( getCurrencyFormatString( '19.80', 'USD' ) ).toBe( '19.80' );
|
||||
global.wcSettings.currency.precision = 2;
|
||||
expect( getCurrencyFormatString( '19.80' ) ).toBe( '19.80' );
|
||||
} );
|
||||
|
||||
it( 'should default to a precision of 2 if none set', () => {
|
||||
delete global.wcSettings.currency.precision;
|
||||
expect( getCurrencyFormatString( '59.282' ) ).toBe( '59.28' );
|
||||
} );
|
||||
|
||||
it( "should return empty string when given an input that isn't a number", () => {
|
||||
expect( getCurrencyFormatString( 'abc', 'USD' ) ).toBe( '' );
|
||||
expect( getCurrencyFormatString( false, 'USD' ) ).toBe( '' );
|
||||
expect( getCurrencyFormatString( null, 'USD' ) ).toBe( '' );
|
||||
global.wcSettings.currency.precision = 2;
|
||||
expect( getCurrencyFormatString( 'abc' ) ).toBe( '' );
|
||||
expect( getCurrencyFormatString( false ) ).toBe( '' );
|
||||
expect( getCurrencyFormatString( null ) ).toBe( '' );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -41,6 +41,8 @@ function woo_dash_register_script() {
|
|||
$settings = array(
|
||||
'adminUrl' => admin_url(),
|
||||
'embedBreadcrumbs' => woo_dash_get_embed_breadcrumbs(),
|
||||
'locale' => esc_attr( get_bloginfo( 'language' ) ),
|
||||
'currency' => woo_dash_currency_settings(),
|
||||
);
|
||||
|
||||
wp_add_inline_script(
|
||||
|
|
|
@ -241,3 +241,26 @@ function woo_dash_get_embed_enabled_plugin_screen_ids() {
|
|||
function woo_dash_get_embed_enabled_screen_ids() {
|
||||
return array_merge( woo_dash_get_embed_enabled_core_screen_ids(), woo_dash_get_embed_enabled_plugin_screen_ids() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an object defining the currecy options for the site's current currency
|
||||
*
|
||||
* @return array Settings for the current currency {
|
||||
* Array of settings.
|
||||
*
|
||||
* @type string $code Currency code.
|
||||
* @type string $precision Number of decimals.
|
||||
* @type string $symbol Symbol for currency.
|
||||
* }
|
||||
*/
|
||||
function woo_dash_currency_settings() {
|
||||
$code = get_woocommerce_currency();
|
||||
|
||||
return apply_filters(
|
||||
'wc_currency_settings', array(
|
||||
'code' => $code,
|
||||
'precision' => wc_get_price_decimals(),
|
||||
'symbol' => get_woocommerce_currency_symbol( $code ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/** @format */
|
||||
|
||||
// Set up `wp.*` aliases. Doing this because any tests importing wp stuff will
|
||||
// likely run into this.
|
||||
global.wp = {
|
||||
|
@ -31,3 +33,9 @@ Object.defineProperty( global.wp, 'element', {
|
|||
Object.defineProperty( global.wp, 'dom', {
|
||||
get: () => require( 'gutenberg/packages/dom' ),
|
||||
} );
|
||||
|
||||
global.wcSettings = {
|
||||
adminUrl: 'https://vagrant.local/wp/wp-admin/',
|
||||
locale: 'en-US',
|
||||
currency: { code: 'USD', precision: 2, symbol: '$' },
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue