Fix attributes/options lists corrupt render (#36236)

* Fix attributes/options lists reordering

* Add changelog

* Fix element key

* Remove comment

* Add tests

* Fix changelog

Co-authored-by: Fernando Marichal <contacto@fernandomarichal.com>
This commit is contained in:
Fernando Marichal 2023-01-03 10:33:29 -03:00 committed by GitHub
parent 216a7505df
commit af9f493c43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 24 deletions

View File

@ -24,7 +24,10 @@ import { getAdminLink } from '@woocommerce/settings';
import './attribute-field.scss';
import { AddAttributeModal } from './add-attribute-modal';
import { EditAttributeModal } from './edit-attribute-modal';
import { reorderSortableProductAttributePositions } from './utils';
import {
getAttributeKey,
reorderSortableProductAttributePositions,
} from './utils';
import { sift } from '../../../utils';
import { AttributeEmptyState } from '../attribute-empty-state';
import {
@ -244,10 +247,10 @@ export const AttributeField: React.FC< AttributeFieldProps > = ( {
);
const attributeKeyValues = filteredAttributes.reduce(
(
keyValue: Record< number, ProductAttribute >,
keyValue: Record< number | string, ProductAttribute >,
attribute: ProductAttribute
) => {
keyValue[ attribute.id ] = attribute;
keyValue[ getAttributeKey( attribute ) ] = attribute;
return keyValue;
},
{} as Record< number, ProductAttribute >

View File

@ -6,7 +6,10 @@ import { ProductAttribute } from '@woocommerce/data';
/**
* Internal dependencies
*/
import { reorderSortableProductAttributePositions } from '../utils';
import {
getAttributeKey,
reorderSortableProductAttributePositions,
} from '../utils';
const attributeList: Record< number, ProductAttribute > = {
15: {
@ -38,9 +41,9 @@ const attributeList: Record< number, ProductAttribute > = {
describe( 'reorderSortableProductAttributePositions', () => {
it( 'should update product attribute positions depending on JSX.Element order', () => {
const elements = [
{ key: '3' },
{ key: '15' },
{ key: '1' },
{ props: { attribute: attributeList[ '3' ] } },
{ props: { attribute: attributeList[ '15' ] } },
{ props: { attribute: attributeList[ '1' ] } },
] as JSX.Element[];
const newList = reorderSortableProductAttributePositions(
elements,
@ -53,19 +56,19 @@ describe( 'reorderSortableProductAttributePositions', () => {
expect( newList[ 2 ].position ).toEqual( 2 );
expect( newList[ 2 ].id ).toEqual( 1 );
} );
} );
it( 'should filter out elements that do not contain a key', () => {
const elements = [
{ key: '3' },
{},
{ key: '15' },
{},
{ key: '1' },
] as JSX.Element[];
const newList = reorderSortableProductAttributePositions(
elements,
attributeList
);
expect( newList.length ).toEqual( 3 );
describe( 'getAttributeKey', () => {
attributeList[ '20' ] = {
id: 0,
name: 'Quality',
position: 3,
visible: true,
variation: true,
options: [ 'low', 'high' ],
};
it( 'should return the attribute key', () => {
expect( getAttributeKey( attributeList[ '15' ] ) ).toEqual( 15 );
expect( getAttributeKey( attributeList[ '20' ] ) ).toEqual( 'Quality' );
} );
} );

View File

@ -3,6 +3,18 @@
*/
import { ProductAttribute } from '@woocommerce/data';
/**
* Returns the attribute key. The key will be the `id` or the `name` when the id is 0.
*
* @param { ProductAttribute } attribute product attribute.
* @return string|number
*/
export function getAttributeKey(
attribute: ProductAttribute
): number | string {
return attribute.id !== 0 ? attribute.id : attribute.name;
}
/**
* Updates the position of a product attribute from the new items JSX.Element list.
*
@ -11,12 +23,12 @@ import { ProductAttribute } from '@woocommerce/data';
*/
export function reorderSortableProductAttributePositions(
items: JSX.Element[],
attributeKeyValues: Record< number, ProductAttribute >
attributeKeyValues: Record< number | string, ProductAttribute >
): ProductAttribute[] {
return items
.map( ( item, index ): ProductAttribute | undefined => {
const key = item.key ? parseInt( item.key as string, 10 ) : NaN;
if ( key !== NaN && attributeKeyValues[ key ] ) {
.map( ( { props }, index ): ProductAttribute | undefined => {
const key = getAttributeKey( props?.attribute );
if ( attributeKeyValues[ key ] ) {
return {
...attributeKeyValues[ key ],
position: index,

View File

@ -0,0 +1,4 @@
Significance: minor
Type: fix
Fix attributes/options lists corrupt render #36236