Price filter: preserve previous constraints while loading (https://github.com/woocommerce/woocommerce-blocks/pull/1386)
* Typo * Save previous constraint while loading * Add tests for formatPrice * Small code refactor * Refactor usePriceConstraints to DRY and add tests * Add base-hooks to jest config
This commit is contained in:
parent
77bb23bf32
commit
af5af78266
|
@ -262,7 +262,7 @@ const PriceSlider = ( {
|
|||
onMouseMove={ findClosestRange }
|
||||
onFocus={ findClosestRange }
|
||||
>
|
||||
{ ! isLoading && hasValidConstraints && (
|
||||
{ hasValidConstraints && (
|
||||
<Fragment>
|
||||
<div
|
||||
className="wc-block-price-filter__range-input-progress"
|
||||
|
@ -281,6 +281,7 @@ const PriceSlider = ( {
|
|||
min={ minConstraint }
|
||||
max={ maxConstraint }
|
||||
ref={ minRange }
|
||||
disabled={ isLoading }
|
||||
/>
|
||||
<input
|
||||
type="range"
|
||||
|
@ -295,6 +296,7 @@ const PriceSlider = ( {
|
|||
min={ minConstraint }
|
||||
max={ maxConstraint }
|
||||
ref={ maxRange }
|
||||
disabled={ isLoading }
|
||||
/>
|
||||
</Fragment>
|
||||
) }
|
||||
|
|
|
@ -9,17 +9,17 @@ import { CURRENCY } from '@woocommerce/settings';
|
|||
*
|
||||
* @param {number} value Number to format.
|
||||
* @param {string} priceFormat Price format string.
|
||||
* @param {string} currencySymbol Curency symbol.
|
||||
* @param {string} currencySymbol Currency symbol.
|
||||
*/
|
||||
export const formatPrice = (
|
||||
value,
|
||||
priceFormat = CURRENCY.price_format,
|
||||
currencySymbol = CURRENCY.symbol
|
||||
) => {
|
||||
if ( value === '' || undefined === value ) {
|
||||
const formattedNumber = parseInt( value, 10 );
|
||||
if ( ! isFinite( formattedNumber ) ) {
|
||||
return '';
|
||||
}
|
||||
const formattedNumber = parseInt( value, 10 );
|
||||
const formattedValue = sprintf(
|
||||
priceFormat,
|
||||
currencySymbol,
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { formatPrice } from '../price';
|
||||
|
||||
describe( 'formatPrice', () => {
|
||||
test.each`
|
||||
value | priceFormat | currencySymbol | expected
|
||||
${10} | ${'%1$s%2$s'} | ${'€'} | ${'€10'}
|
||||
${10} | ${'%2$s%1$s'} | ${'€'} | ${'10€'}
|
||||
${10} | ${'%2$s%1$s'} | ${'$'} | ${'10$'}
|
||||
${'10'} | ${'%1$s%2$s'} | ${'€'} | ${'€10'}
|
||||
${0} | ${'%1$s%2$s'} | ${'€'} | ${'€0'}
|
||||
${''} | ${'%1$s%2$s'} | ${'€'} | ${''}
|
||||
${null} | ${'%1$s%2$s'} | ${'€'} | ${''}
|
||||
${undefined} | ${'%1$s%2$s'} | ${'€'} | ${''}
|
||||
`(
|
||||
'correctly formats price given "$value", "$priceFormat", and "$currencySymbol"',
|
||||
( { value, priceFormat, currencySymbol, expected } ) => {
|
||||
const formattedPrice = formatPrice(
|
||||
value,
|
||||
priceFormat,
|
||||
currencySymbol
|
||||
);
|
||||
|
||||
expect( formattedPrice ).toEqual( expected );
|
||||
}
|
||||
);
|
||||
} );
|
|
@ -12,6 +12,11 @@ import { CURRENCY } from '@woocommerce/settings';
|
|||
import { useDebouncedCallback } from 'use-debounce';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import usePriceConstraints from './use-price-constraints.js';
|
||||
|
||||
/**
|
||||
* Component displaying a price filter.
|
||||
*/
|
||||
|
@ -31,12 +36,10 @@ const PriceFilterBlock = ( { attributes, isEditor = false } ) => {
|
|||
const [ minPrice, setMinPrice ] = useState();
|
||||
const [ maxPrice, setMaxPrice ] = useState();
|
||||
|
||||
const minConstraint = isNaN( results.min_price )
|
||||
? null
|
||||
: Math.floor( parseInt( results.min_price, 10 ) / 10 ) * 10;
|
||||
const maxConstraint = isNaN( results.max_price )
|
||||
? null
|
||||
: Math.ceil( parseInt( results.max_price, 10 ) / 10 ) * 10;
|
||||
const { minConstraint, maxConstraint } = usePriceConstraints( {
|
||||
minPrice: results.min_price,
|
||||
maxPrice: results.max_price,
|
||||
} );
|
||||
|
||||
// Updates the query after a short delay.
|
||||
const [ debouncedUpdateQuery ] = useDebouncedCallback( () => {
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import TestRenderer from 'react-test-renderer';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { usePriceConstraint } from '../use-price-constraints';
|
||||
|
||||
describe( 'usePriceConstraints', () => {
|
||||
const TestComponent = ( { price } ) => {
|
||||
const priceConstraint = usePriceConstraint( price );
|
||||
return <div priceConstraint={ priceConstraint } />;
|
||||
};
|
||||
|
||||
it( 'price constraint should be updated when new price is set', () => {
|
||||
const renderer = TestRenderer.create( <TestComponent price={ 10 } /> );
|
||||
const container = renderer.root.findByType( 'div' );
|
||||
|
||||
expect( container.props.priceConstraint ).toBe( 10 );
|
||||
|
||||
renderer.update( <TestComponent price={ 20 } /> );
|
||||
|
||||
expect( container.props.priceConstraint ).toBe( 20 );
|
||||
} );
|
||||
|
||||
it( 'previous price constraint should be preserved when new price is not a infinite number', () => {
|
||||
const renderer = TestRenderer.create( <TestComponent price={ 10 } /> );
|
||||
const container = renderer.root.findByType( 'div' );
|
||||
|
||||
expect( container.props.priceConstraint ).toBe( 10 );
|
||||
|
||||
renderer.update( <TestComponent price={ Infinity } /> );
|
||||
|
||||
expect( container.props.priceConstraint ).toBe( 10 );
|
||||
} );
|
||||
} );
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { usePrevious } from '@woocommerce/base-hooks';
|
||||
|
||||
export const usePriceConstraint = ( price ) => {
|
||||
const currentConstraint = isNaN( price )
|
||||
? null
|
||||
: Math.floor( parseInt( price, 10 ) / 10 ) * 10;
|
||||
const previousConstraint = usePrevious( currentConstraint, ( val ) =>
|
||||
Number.isFinite( val )
|
||||
);
|
||||
return Number.isFinite( currentConstraint )
|
||||
? currentConstraint
|
||||
: previousConstraint;
|
||||
};
|
||||
|
||||
export default ( { minPrice, maxPrice } ) => {
|
||||
return {
|
||||
minConstraint: usePriceConstraint( minPrice ),
|
||||
maxConstraint: usePriceConstraint( maxPrice ),
|
||||
};
|
||||
};
|
|
@ -15,6 +15,7 @@
|
|||
"@woocommerce/base-components(.*)$": "assets/js/base/components/$1",
|
||||
"@woocommerce/base-context(.*)$": "assets/js/base/context/$1",
|
||||
"@woocommerce/base-hocs(.*)$": "assets/js/base/hocs/$1",
|
||||
"@woocommerce/base-hooks(.*)$": "assets/js/base/hooks/$1",
|
||||
"@woocommerce/block-data": "assets/js/data"
|
||||
},
|
||||
"setupFiles": [
|
||||
|
|
Loading…
Reference in New Issue