OBW: Hide the extensions header when no available plugins in the category (https://github.com/woocommerce/woocommerce-admin/pull/8089)

* Hide extension list header if no plugins under the category

* Refactor variable naming and add missing hook deps

* Add changelogs

* Add tests for <ExtensionSection />
This commit is contained in:
Chi-Hsuan Huang 2021-12-29 16:32:19 +08:00 committed by GitHub
parent a0278af8ad
commit ac78e74ef6
4 changed files with 121 additions and 49 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: Fix
Hide the extensions header when no available plugins in the category. #8089

View File

@ -159,8 +159,44 @@ const BundleExtensionCheckbox = ( { onChange, description, isChecked } ) => {
); );
}; };
const baseValues = { install_extensions: true }; export const ExtensionSection = ( {
export const createInitialValues = ( extensions ) => { isResolving,
title,
extensions,
installExtensionOptions,
onCheckboxChange,
} ) => {
if ( isResolving ) {
return (
<div>
<Spinner />
</div>
);
}
if ( extensions.length === 0 ) {
return null;
}
return (
<div>
<div className="woocommerce-admin__business-details__selective-extensions-bundle__category">
{ title }
</div>
{ extensions.map( ( { description, key } ) => (
<BundleExtensionCheckbox
key={ key }
description={ description }
isChecked={ installExtensionOptions[ key ] }
onChange={ onCheckboxChange( key ) }
/>
) ) }
</div>
);
};
export const createInstallExtensionOptions = ( extensions = [] ) => {
const defaultInstallExtensionOptions = { install_extensions: true };
return extensions.reduce( ( acc, curr ) => { return extensions.reduce( ( acc, curr ) => {
const plugins = curr.plugins.reduce( const plugins = curr.plugins.reduce(
( pluginAcc, { key, selected } ) => { ( pluginAcc, { key, selected } ) => {
@ -173,7 +209,7 @@ export const createInitialValues = ( extensions ) => {
...acc, ...acc,
...plugins, ...plugins,
}; };
}, baseValues ); }, defaultInstallExtensionOptions );
}; };
export const SelectiveExtensionsBundle = ( { export const SelectiveExtensionsBundle = ( {
@ -181,7 +217,9 @@ export const SelectiveExtensionsBundle = ( {
onSubmit, onSubmit,
} ) => { } ) => {
const [ showExtensions, setShowExtensions ] = useState( false ); const [ showExtensions, setShowExtensions ] = useState( false );
const [ values, setValues ] = useState( baseValues ); const [ installExtensionOptions, setInstallExtensionOptions ] = useState(
createInstallExtensionOptions()
);
const { const {
countryCode, countryCode,
@ -224,19 +262,20 @@ export const SelectiveExtensionsBundle = ( {
} }
return ALLOWED_PLUGIN_LISTS.includes( list.key ); return ALLOWED_PLUGIN_LISTS.includes( list.key );
} ); } );
}, [ freeExtensions, profileItems ] ); }, [ freeExtensions, profileItems, countryCode ] );
useEffect( () => { useEffect( () => {
if ( ! isInstallingActivating ) { if ( ! isInstallingActivating ) {
const initialValues = createInitialValues( installableExtensions ); setInstallExtensionOptions(
setValues( initialValues ); createInstallExtensionOptions( installableExtensions )
);
} }
}, [ installableExtensions ] ); }, [ installableExtensions, isInstallingActivating ] );
const getCheckboxChangeHandler = ( key ) => { const getCheckboxChangeHandler = ( key ) => {
return ( checked ) => { return ( checked ) => {
const newState = { const newState = {
...values, ...installExtensionOptions,
[ key ]: checked, [ key ]: checked,
}; };
@ -246,13 +285,13 @@ export const SelectiveExtensionsBundle = ( {
if ( allExtensionsDisabled ) { if ( allExtensionsDisabled ) {
// If all the extensions are disabled then disable the "Install Extensions" checkbox too // If all the extensions are disabled then disable the "Install Extensions" checkbox too
setValues( { setInstallExtensionOptions( {
...newState, ...newState,
install_extensions: false, install_extensions: false,
} ); } );
} else { } else {
setValues( { setInstallExtensionOptions( {
...values, ...installExtensionOptions,
[ key ]: checked, [ key ]: checked,
install_extensions: true, install_extensions: true,
} ); } );
@ -269,10 +308,15 @@ export const SelectiveExtensionsBundle = ( {
<div className="woocommerce-admin__business-details__selective-extensions-bundle"> <div className="woocommerce-admin__business-details__selective-extensions-bundle">
<div className="woocommerce-admin__business-details__selective-extensions-bundle__extension"> <div className="woocommerce-admin__business-details__selective-extensions-bundle__extension">
<CheckboxControl <CheckboxControl
checked={ values.install_extensions } checked={
installExtensionOptions.install_extensions
}
onChange={ ( checked ) => { onChange={ ( checked ) => {
setValues( setInstallExtensionOptions(
setAllPropsToValue( values, checked ) setAllPropsToValue(
installExtensionOptions,
checked
)
); );
} } } }
/> />
@ -308,41 +352,25 @@ export const SelectiveExtensionsBundle = ( {
</div> </div>
{ showExtensions && { showExtensions &&
installableExtensions.map( installableExtensions.map(
( { plugins, key: sectionKey, title } ) => ( ( { plugins, key, title } ) => (
<div key={ sectionKey }> <ExtensionSection
{ isResolving ? (
<Spinner />
) : (
<>
<div className="woocommerce-admin__business-details__selective-extensions-bundle__category">
{ title }
</div>
{ plugins.map(
( { description, key } ) => (
<BundleExtensionCheckbox
key={ key } key={ key }
description={ title={ title }
description extensions={ plugins }
installExtensionOptions={
installExtensionOptions
} }
isChecked={ onCheckboxChange={
values[ key ] getCheckboxChangeHandler
} }
onChange={ getCheckboxChangeHandler(
key
) }
/> />
) )
) } ) }
</>
) }
</div>
)
) }
</div> </div>
<div className="woocommerce-profile-wizard__business-details__free-features__action"> <div className="woocommerce-profile-wizard__business-details__free-features__action">
<Button <Button
onClick={ () => { onClick={ () => {
onSubmit( values ); onSubmit( installExtensionOptions );
} } } }
isBusy={ isInstallingActivating || isResolving } isBusy={ isInstallingActivating || isResolving }
disabled={ isInstallingActivating || isResolving } disabled={ isInstallingActivating || isResolving }
@ -353,7 +381,7 @@ export const SelectiveExtensionsBundle = ( {
</div> </div>
</Card> </Card>
{ renderBusinessExtensionHelpText( { renderBusinessExtensionHelpText(
values, installExtensionOptions,
isInstallingActivating isInstallingActivating
) } ) }
</div> </div>

View File

@ -9,7 +9,7 @@ import { pluginNames } from '@woocommerce/data';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { SelectiveExtensionsBundle } from '../'; import { SelectiveExtensionsBundle, ExtensionSection } from '../';
jest.mock( '../../app-illustration', () => ( { jest.mock( '../../app-illustration', () => ( {
AppIllustration: jest.fn().mockReturnValue( '[illustration]' ), AppIllustration: jest.fn().mockReturnValue( '[illustration]' ),
@ -129,4 +129,39 @@ describe( 'Selective extensions bundle', () => {
expect( queryByText( 'Google Description' ) ).toBeInTheDocument(); expect( queryByText( 'Google Description' ) ).toBeInTheDocument();
expect( queryByText( 'Random Description' ) ).not.toBeInTheDocument(); expect( queryByText( 'Random Description' ) ).not.toBeInTheDocument();
} ); } );
describe( '<ExtensionSection />', () => {
it( 'should render title and extensions', () => {
const title = 'This is title';
const { queryByText } = render(
<ExtensionSection
isResolving={ false }
title={ title }
extensions={ freeExtensions[ 0 ].plugins }
installExtensionOptions={ {} }
onCheckboxChange={ () => {} }
/>
);
expect( queryByText( title ) ).toBeInTheDocument();
freeExtensions[ 0 ].plugins.forEach( ( { description } ) => {
expect( queryByText( description ) ).toBeInTheDocument();
} );
} );
it( 'should render not title when no plugins', () => {
const title = 'This is title';
const { queryByText } = render(
<ExtensionSection
isResolving={ false }
title={ title }
extensions={ [] }
installExtensionOptions={ {} }
onCheckboxChange={ () => {} }
/>
);
expect( queryByText( title ) ).not.toBeInTheDocument();
} );
} );
} ); } );

View File

@ -5,7 +5,7 @@ import {
filterBusinessExtensions, filterBusinessExtensions,
prepareExtensionTrackingData, prepareExtensionTrackingData,
} from '../flows/selective-bundle'; } from '../flows/selective-bundle';
import { createInitialValues } from '../flows/selective-bundle/selective-extensions-bundle'; import { createInstallExtensionOptions } from '../flows/selective-bundle/selective-extensions-bundle';
describe( 'BusinessDetails', () => { describe( 'BusinessDetails', () => {
test( 'filtering extensions', () => { test( 'filtering extensions', () => {
@ -101,7 +101,7 @@ describe( 'BusinessDetails', () => {
} ); } );
} ); } );
describe( 'createInitialValues', () => { describe( 'createInstallExtensionOptions', () => {
test( 'selected by default', () => { test( 'selected by default', () => {
const extensions = [ const extensions = [
{ {
@ -125,7 +125,12 @@ describe( 'BusinessDetails', () => {
}, },
]; ];
const values = createInitialValues( extensions, 'US', '', [] ); const values = createInstallExtensionOptions(
extensions,
'US',
'',
[]
);
expect( values ).toEqual( expect( values ).toEqual(
expect.objectContaining( { expect.objectContaining( {