Navigation: Add test to container component (https://github.com/woocommerce/woocommerce-admin/pull/6344)
* getCategoriesMap * getMenuItemsByCategory * changelog
This commit is contained in:
parent
8371325ba6
commit
3483f1930e
|
@ -22,23 +22,22 @@ import CategoryTitle from '../category-title';
|
|||
import Header from '../header';
|
||||
import Item from '../../components/Item';
|
||||
|
||||
const Container = ( { menuItems } ) => {
|
||||
useEffect( () => {
|
||||
// Collapse the original WP Menu.
|
||||
document.documentElement.classList.remove( 'wp-toolbar' );
|
||||
document.body.classList.add( 'has-woocommerce-navigation' );
|
||||
const adminMenu = document.getElementById( 'adminmenumain' );
|
||||
|
||||
if ( ! adminMenu ) {
|
||||
return;
|
||||
/**
|
||||
* Get a map of all categories, including the topmost WooCommerce parentCategory
|
||||
*
|
||||
* @param {Array} menuItems Array of menuItems
|
||||
* @return {Object} Map of categories by id
|
||||
*/
|
||||
export const getCategoriesMap = ( menuItems ) => {
|
||||
return menuItems.reduce(
|
||||
( acc, item ) => {
|
||||
if ( item.isCategory ) {
|
||||
return { ...acc, [ item.id ]: item };
|
||||
}
|
||||
|
||||
adminMenu.classList.add( 'folded' );
|
||||
}, [] );
|
||||
|
||||
const { rootBackLabel, rootBackUrl } = window.wcNavigation;
|
||||
|
||||
const parentCategory = {
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
woocommerce: {
|
||||
capability: 'manage_woocommerce',
|
||||
id: 'woocommerce',
|
||||
isCategory: true,
|
||||
|
@ -47,44 +46,20 @@ const Container = ( { menuItems } ) => {
|
|||
order: 10,
|
||||
parent: '',
|
||||
title: 'WooCommerce',
|
||||
};
|
||||
const categoriesMap = menuItems.reduce(
|
||||
( acc, item ) => {
|
||||
if ( item.isCategory ) {
|
||||
return { ...acc, [ item.id ]: item };
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
woocommerce: parentCategory,
|
||||
}
|
||||
);
|
||||
const categories = Object.values( categoriesMap );
|
||||
};
|
||||
|
||||
const [ activeItem, setActiveItem ] = useState( 'woocommerce-home' );
|
||||
const [ activeLevel, setActiveLevel ] = useState( 'woocommerce' );
|
||||
|
||||
useEffect( () => {
|
||||
const initialMatchedItem = getMatchingItem( menuItems );
|
||||
if ( initialMatchedItem && activeItem !== initialMatchedItem ) {
|
||||
setActiveItem( initialMatchedItem );
|
||||
setActiveLevel( initialMatchedItem.parent );
|
||||
}
|
||||
|
||||
const removeListener = addHistoryListener( () => {
|
||||
setTimeout( () => {
|
||||
const matchedItem = getMatchingItem( menuItems );
|
||||
if ( matchedItem ) {
|
||||
setActiveItem( matchedItem );
|
||||
}
|
||||
}, 0 );
|
||||
} );
|
||||
|
||||
return removeListener;
|
||||
}, [ menuItems ] );
|
||||
|
||||
const getMenuItemsByCategory = ( items ) => {
|
||||
return items.reduce( ( acc, item ) => {
|
||||
/**
|
||||
* Get a flat tree structure of all Categories and thier children grouped by menuId
|
||||
*
|
||||
* @param {Object} categoriesMap Map of categories by id
|
||||
* @param {Array} menuItems Array of menuItems
|
||||
* @return {Object} a;dslkfj
|
||||
*/
|
||||
export const getMenuItemsByCategory = ( categoriesMap, menuItems ) => {
|
||||
return menuItems.reduce( ( acc, item ) => {
|
||||
// Set up the category if it doesn't yet exist.
|
||||
if ( ! acc[ item.parent ] ) {
|
||||
acc[ item.parent ] = {};
|
||||
|
@ -109,11 +84,52 @@ const Container = ( { menuItems } ) => {
|
|||
acc[ item.parent ][ item.menuId ].push( item );
|
||||
return acc;
|
||||
}, {} );
|
||||
};
|
||||
};
|
||||
|
||||
const Container = ( { menuItems } ) => {
|
||||
useEffect( () => {
|
||||
// Collapse the original WP Menu.
|
||||
document.documentElement.classList.remove( 'wp-toolbar' );
|
||||
document.body.classList.add( 'has-woocommerce-navigation' );
|
||||
const adminMenu = document.getElementById( 'adminmenumain' );
|
||||
|
||||
if ( ! adminMenu ) {
|
||||
return;
|
||||
}
|
||||
|
||||
adminMenu.classList.add( 'folded' );
|
||||
}, [] );
|
||||
|
||||
const { rootBackLabel, rootBackUrl } = window.wcNavigation;
|
||||
|
||||
const categoriesMap = getCategoriesMap( menuItems );
|
||||
const categories = Object.values( categoriesMap );
|
||||
|
||||
const [ activeItem, setActiveItem ] = useState( 'woocommerce-home' );
|
||||
const [ activeLevel, setActiveLevel ] = useState( 'woocommerce' );
|
||||
|
||||
useEffect( () => {
|
||||
const initialMatchedItem = getMatchingItem( menuItems );
|
||||
if ( initialMatchedItem && activeItem !== initialMatchedItem ) {
|
||||
setActiveItem( initialMatchedItem );
|
||||
setActiveLevel( initialMatchedItem.parent );
|
||||
}
|
||||
|
||||
const removeListener = addHistoryListener( () => {
|
||||
setTimeout( () => {
|
||||
const matchedItem = getMatchingItem( menuItems );
|
||||
if ( matchedItem ) {
|
||||
setActiveItem( matchedItem );
|
||||
}
|
||||
}, 0 );
|
||||
} );
|
||||
|
||||
return removeListener;
|
||||
}, [ menuItems ] );
|
||||
|
||||
const categorizedItems = useMemo(
|
||||
() => getMenuItemsByCategory( menuItems ),
|
||||
[ menuItems ]
|
||||
() => getMenuItemsByCategory( categoriesMap, menuItems ),
|
||||
[ categoriesMap, menuItems ]
|
||||
);
|
||||
|
||||
const navDomRef = useRef( null );
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getCategoriesMap, getMenuItemsByCategory } from '../';
|
||||
|
||||
describe( 'getCategoriesMap', () => {
|
||||
const menuItems = [
|
||||
{ id: 'zero', title: 'zero', isCategory: true },
|
||||
{ id: 'one', title: 'one', isCategory: true },
|
||||
{ id: 'two', title: 'two', isCategory: true },
|
||||
{ id: 'three', title: 'three', isCategory: false },
|
||||
{ id: 'four', title: 'four', isCategory: false },
|
||||
];
|
||||
|
||||
it( 'should get a map of all categories', () => {
|
||||
const categoriesMap = getCategoriesMap( menuItems );
|
||||
|
||||
expect( categoriesMap.zero ).toMatchObject( menuItems[ 0 ] );
|
||||
expect( categoriesMap.one ).toMatchObject( menuItems[ 1 ] );
|
||||
expect( categoriesMap.two ).toMatchObject( menuItems[ 2 ] );
|
||||
expect( categoriesMap.three ).toBeUndefined();
|
||||
expect( categoriesMap.four ).toBeUndefined();
|
||||
} );
|
||||
|
||||
it( 'should include the topmost WooCommerce parent category', () => {
|
||||
const categoriesMap = getCategoriesMap( menuItems );
|
||||
|
||||
expect( categoriesMap.woocommerce ).toBeDefined();
|
||||
} );
|
||||
|
||||
it( 'should have the correct number of values', () => {
|
||||
const categoriesMap = getCategoriesMap( menuItems );
|
||||
|
||||
expect( Object.keys( categoriesMap ).length ).toBe( 4 );
|
||||
} );
|
||||
} );
|
||||
|
||||
describe( 'getMenuItemsByCategory', () => {
|
||||
it( 'should get a map of all categories and child elements', () => {
|
||||
const menuItems = [
|
||||
{
|
||||
id: 'child-one',
|
||||
title: 'child-one',
|
||||
isCategory: false,
|
||||
parent: 'parent',
|
||||
menuId: 'plugins',
|
||||
},
|
||||
{
|
||||
id: 'child-two',
|
||||
title: 'child-two',
|
||||
isCategory: false,
|
||||
parent: 'parent',
|
||||
menuId: 'plugins',
|
||||
},
|
||||
{
|
||||
id: 'parent',
|
||||
title: 'parent',
|
||||
isCategory: true,
|
||||
parent: 'woocommerce',
|
||||
menuId: 'plugins',
|
||||
},
|
||||
];
|
||||
const categoriesMap = getCategoriesMap( menuItems );
|
||||
const categorizedItems = getMenuItemsByCategory(
|
||||
categoriesMap,
|
||||
menuItems
|
||||
);
|
||||
|
||||
expect( categorizedItems.woocommerce ).toBeDefined();
|
||||
expect( categorizedItems.woocommerce.plugins ).toBeDefined();
|
||||
expect( categorizedItems.woocommerce.plugins.length ).toBe( 1 );
|
||||
|
||||
expect( categorizedItems.parent ).toBeDefined();
|
||||
expect( categorizedItems.parent.plugins ).toBeDefined();
|
||||
expect( categorizedItems.parent.plugins.length ).toBe( 2 );
|
||||
} );
|
||||
|
||||
it( 'should handle multiple depths', () => {
|
||||
const menuItems = [
|
||||
{
|
||||
id: 'grand-child',
|
||||
title: 'grand-child',
|
||||
isCategory: false,
|
||||
parent: 'child',
|
||||
menuId: 'plugins',
|
||||
},
|
||||
{
|
||||
id: 'child',
|
||||
title: 'child',
|
||||
isCategory: true,
|
||||
parent: 'grand-parent',
|
||||
menuId: 'plugins',
|
||||
},
|
||||
{
|
||||
id: 'grand-parent',
|
||||
title: 'grand-parent',
|
||||
isCategory: true,
|
||||
parent: 'woocommerce',
|
||||
menuId: 'plugins',
|
||||
},
|
||||
];
|
||||
const categoriesMap = getCategoriesMap( menuItems );
|
||||
const categorizedItems = getMenuItemsByCategory(
|
||||
categoriesMap,
|
||||
menuItems
|
||||
);
|
||||
|
||||
expect( categorizedItems[ 'grand-parent' ] ).toBeDefined();
|
||||
expect( categorizedItems[ 'grand-parent' ] ).toBeDefined();
|
||||
expect( categorizedItems[ 'grand-parent' ].plugins.length ).toBe( 1 );
|
||||
|
||||
expect( categorizedItems.child ).toBeDefined();
|
||||
expect( categorizedItems.child ).toBeDefined();
|
||||
expect( categorizedItems.child.plugins.length ).toBe( 1 );
|
||||
|
||||
expect( categorizedItems[ 'grand-child' ] ).not.toBeDefined();
|
||||
} );
|
||||
|
||||
it( 'should group by menuId', () => {
|
||||
const menuItems = [
|
||||
{
|
||||
id: 'parent',
|
||||
title: 'parent',
|
||||
isCategory: true,
|
||||
parent: 'woocommerce',
|
||||
menuId: 'primary',
|
||||
},
|
||||
{
|
||||
id: 'primary-one',
|
||||
title: 'primary-one',
|
||||
isCategory: false,
|
||||
parent: 'parent',
|
||||
menuId: 'primary',
|
||||
},
|
||||
{
|
||||
id: 'primary-two',
|
||||
title: 'primary-two',
|
||||
isCategory: false,
|
||||
parent: 'parent',
|
||||
menuId: 'primary',
|
||||
},
|
||||
];
|
||||
const categoriesMap = getCategoriesMap( menuItems );
|
||||
const categorizedItems = getMenuItemsByCategory(
|
||||
categoriesMap,
|
||||
menuItems
|
||||
);
|
||||
|
||||
expect( categorizedItems.parent ).toBeDefined();
|
||||
expect( categorizedItems.parent.primary ).toBeDefined();
|
||||
expect( categorizedItems.parent.primary.length ).toBe( 2 );
|
||||
} );
|
||||
|
||||
it( 'should group children only if their menuId matches parent', () => {
|
||||
const menuItems = [
|
||||
{
|
||||
id: 'plugin-one',
|
||||
title: 'plugin-one',
|
||||
isCategory: false,
|
||||
parent: 'parent',
|
||||
menuId: 'plugins',
|
||||
},
|
||||
{
|
||||
id: 'plugin-two',
|
||||
title: 'plugin-two',
|
||||
isCategory: false,
|
||||
parent: 'parent',
|
||||
menuId: 'plugins',
|
||||
},
|
||||
{
|
||||
id: 'parent',
|
||||
title: 'parent',
|
||||
isCategory: true,
|
||||
parent: 'woocommerce',
|
||||
menuId: 'plugins',
|
||||
},
|
||||
{
|
||||
id: 'primary-one',
|
||||
title: 'primary-one',
|
||||
isCategory: false,
|
||||
parent: 'parent',
|
||||
menuId: 'primary',
|
||||
},
|
||||
{
|
||||
id: 'primary-two',
|
||||
title: 'primary-two',
|
||||
isCategory: false,
|
||||
parent: 'parent',
|
||||
menuId: 'primary',
|
||||
},
|
||||
];
|
||||
const categoriesMap = getCategoriesMap( menuItems );
|
||||
const categorizedItems = getMenuItemsByCategory(
|
||||
categoriesMap,
|
||||
menuItems
|
||||
);
|
||||
|
||||
expect( categorizedItems.parent ).toBeDefined();
|
||||
expect( categorizedItems.parent.plugins ).toBeDefined();
|
||||
expect( categorizedItems.parent.plugins.length ).toBe( 2 );
|
||||
|
||||
expect( categorizedItems.primary ).not.toBeDefined();
|
||||
} );
|
||||
} );
|
|
@ -48,6 +48,7 @@
|
|||
"config": "^3.2.4",
|
||||
"eslint": "6.7.2",
|
||||
"jest": "^24.9.0",
|
||||
"prettier": "npm:wp-prettier@1.19.1",
|
||||
"puppeteer": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -142,6 +143,11 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"prettier": {
|
||||
"version": "npm:wp-prettier@1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-1.19.1.tgz",
|
||||
"integrity": "sha512-mqAC2r1NDmRjG+z3KCJ/i61tycKlmADIjxnDhQab+KBxSAGbF/W7/zwB2guy/ypIeKrrftNsIYkNZZQKf3vJcg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -9049,8 +9055,7 @@
|
|||
}
|
||||
},
|
||||
"@woocommerce/currency": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "/mnt/renovate/gh/woocommerce/woocommerce-admin/packages/currency",
|
||||
"version": "file:packages/currency",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime-corejs2": "7.12.5",
|
||||
|
@ -9167,8 +9172,7 @@
|
|||
}
|
||||
},
|
||||
"@woocommerce/data": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "/mnt/renovate/gh/woocommerce/woocommerce-admin/packages/data",
|
||||
"version": "file:packages/data",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime-corejs2": "7.12.5",
|
||||
|
@ -9178,8 +9182,7 @@
|
|||
}
|
||||
},
|
||||
"@woocommerce/date": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "/mnt/renovate/gh/woocommerce/woocommerce-admin/packages/date",
|
||||
"version": "file:packages/date",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/runtime-corejs2": "7.12.5",
|
||||
|
@ -10192,8 +10195,7 @@
|
|||
}
|
||||
},
|
||||
"@woocommerce/navigation": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "/mnt/renovate/gh/woocommerce/woocommerce-admin/packages/navigation",
|
||||
"version": "file:packages/navigation",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "4.17.15"
|
||||
|
|
|
@ -78,6 +78,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt
|
|||
- Dev: Allow highlight tooltip to use body tag as parent. #6309
|
||||
- Dev: Remove Google fonts and material icons. #6343
|
||||
- Add: Remove CES actions for adding and editing a product and editing an order #6355
|
||||
- Dev: Add unit tests to Navigation's Container component. #6344
|
||||
|
||||
== 2.0.0 02/05/2021 ==
|
||||
|
||||
|
|
Loading…
Reference in New Issue