Make `Search` accept sync `autocompleter.options.` (https://github.com/woocommerce/woocommerce-admin/pull/6884)
Co-authored-by: Jeff Stieler <jeff.m.stieler@gmail.com> Make `Search` component accept `autocompleter.options` that meet the requirements stated in [the docs](https://github.com/WordPress/gutenberg/tree/trunk/packages/components/src/autocomplete#options): > May be an array, a function that returns an array, or a function that returns a promise for an array. Fixes https://github.com/woocommerce/woocommerce-admin/issues/6061.
This commit is contained in:
parent
0f4c102c51
commit
6aa78cbdb9
|
@ -1,5 +1,6 @@
|
|||
# Unreleased
|
||||
|
||||
- Make `Search` accept synchronous `autocompleter.options`. #6884
|
||||
- Add new (experimental) collapsible list item to collapse list items. #6869
|
||||
- SelectControl: fix display of multiple selections without inline tags. #6862
|
||||
- Add new (experimental) list, and add depreciation notice for the current list. #6787
|
||||
|
|
|
@ -108,8 +108,15 @@ export class Search extends Component {
|
|||
return [];
|
||||
}
|
||||
|
||||
const autocompleter = this.getAutocompleter();
|
||||
return autocompleter.options( query ).then( async ( response ) => {
|
||||
const autocompleterOptions = this.getAutocompleter().options;
|
||||
|
||||
// Support arrays, sync- & async functions that returns an array.
|
||||
const resolvedOptions = Promise.resolve(
|
||||
typeof autocompleterOptions === 'function'
|
||||
? autocompleterOptions( query )
|
||||
: autocompleterOptions || []
|
||||
);
|
||||
return resolvedOptions.then( async ( response ) => {
|
||||
const options = this.getFormattedOptions( response, query );
|
||||
this.setState( { options } );
|
||||
return options;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { render } from '@testing-library/react';
|
||||
import { render, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
/**
|
||||
|
@ -10,8 +10,11 @@ import userEvent from '@testing-library/user-event';
|
|||
import { Search } from '../index';
|
||||
import { computeSuggestionMatch } from '../autocompleters/utils';
|
||||
|
||||
const delay = ( timeout ) =>
|
||||
new Promise( ( resolve ) => setTimeout( resolve, timeout ) );
|
||||
|
||||
describe( 'Search', () => {
|
||||
it( 'shows the free text search option', async () => {
|
||||
it( 'shows the free text search option', () => {
|
||||
const { getByRole, queryAllByRole } = render(
|
||||
<Search type="products" allowFreeTextSearch />
|
||||
);
|
||||
|
@ -22,6 +25,103 @@ describe( 'Search', () => {
|
|||
expect( queryAllByRole( 'option' ) ).toHaveLength( 0 );
|
||||
} );
|
||||
|
||||
describe( 'with `type="custom"`', () => {
|
||||
let sampleOptions, sampleAutocompleter;
|
||||
beforeEach( () => {
|
||||
sampleOptions = [
|
||||
{ name: 'Apple', id: 1 },
|
||||
{ name: 'Orange', id: 2 },
|
||||
{ name: 'Grapes', id: 3 },
|
||||
];
|
||||
sampleAutocompleter = {
|
||||
options: sampleOptions,
|
||||
getOptionIdentifier: ( fruit ) => fruit.id,
|
||||
getOptionLabel: ( option ) => (
|
||||
<nicer-label>{ option.name }</nicer-label>
|
||||
),
|
||||
getOptionKeywords: ( option ) => [ option.name ],
|
||||
getOptionCompletion: ( attribute ) => ( {
|
||||
key: attribute.id,
|
||||
label: attribute.name,
|
||||
} ),
|
||||
};
|
||||
} );
|
||||
describe( 'renders options given in `autocompleter.options`', () => {
|
||||
it( 'as a static array', async () => {
|
||||
const { getByRole, queryAllByRole } = render(
|
||||
<Search
|
||||
type="custom"
|
||||
autocompleter={ sampleAutocompleter }
|
||||
/>
|
||||
);
|
||||
// Emulate typing to render available options.
|
||||
userEvent.type( getByRole( 'combobox' ), 'A' );
|
||||
// Wait for async options procesing.
|
||||
await waitFor( () => {
|
||||
expect( queryAllByRole( 'option' ) ).toHaveLength( 3 );
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'being a function that for the given query returns an array', async () => {
|
||||
const optionsSpy = jest
|
||||
.fn()
|
||||
.mockName( 'autocompleter.options' );
|
||||
|
||||
const customAutocompleter = {
|
||||
...sampleAutocompleter,
|
||||
// Set the options as a function that returns an array.
|
||||
options: ( ...args ) => {
|
||||
optionsSpy( ...args );
|
||||
return sampleOptions;
|
||||
},
|
||||
};
|
||||
|
||||
const { getByRole, queryAllByRole } = render(
|
||||
<Search
|
||||
type="custom"
|
||||
autocompleter={ customAutocompleter }
|
||||
/>
|
||||
);
|
||||
// Emulate typing to render available options.
|
||||
userEvent.type( getByRole( 'combobox' ), 'A' );
|
||||
// Wait for async options procesing.
|
||||
await waitFor( () => {
|
||||
expect( optionsSpy ).toBeCalledWith( 'A' );
|
||||
expect( queryAllByRole( 'option' ) ).toHaveLength( 3 );
|
||||
} );
|
||||
} );
|
||||
|
||||
it( 'being a function that for the given query returns a promise for an array', async () => {
|
||||
const optionsSpy = jest
|
||||
.fn()
|
||||
.mockName( 'autocompleter.options' );
|
||||
|
||||
const customAutocompleter = {
|
||||
...sampleAutocompleter,
|
||||
// Set the options as a function that returns a promise for an array.
|
||||
options: async ( ...args ) => {
|
||||
optionsSpy( ...args );
|
||||
await delay( 1 );
|
||||
return sampleOptions;
|
||||
},
|
||||
};
|
||||
|
||||
const { getByRole, queryAllByRole } = render(
|
||||
<Search
|
||||
type="custom"
|
||||
autocompleter={ customAutocompleter }
|
||||
/>
|
||||
);
|
||||
// Emulate typing to render available options.
|
||||
userEvent.type( getByRole( 'combobox' ), 'A' );
|
||||
// Wait for async options procesing.
|
||||
await waitFor( () => {
|
||||
expect( optionsSpy ).toBeCalledWith( 'A' );
|
||||
expect( queryAllByRole( 'option' ) ).toHaveLength( 3 );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
it( 'returns an object with decoded text', () => {
|
||||
const decodedText = computeSuggestionMatch(
|
||||
'A test & a test',
|
||||
|
|
|
@ -75,6 +75,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt
|
|||
|
||||
== Unreleased ==
|
||||
|
||||
- Fix: Make `Search` accept synchronous `autocompleter.options`. #6884
|
||||
- Add: Consume remote payment methods on frontend #6867
|
||||
- Add: Add plugin installer to allow installation of plugins via URL #6805
|
||||
- Add: Optional children prop to SummaryNumber component #6748
|
||||
|
|
Loading…
Reference in New Issue