diff --git a/plugins/woocommerce-admin/package-lock.json b/plugins/woocommerce-admin/package-lock.json
index c86be0b0860..50733e69f1c 100644
--- a/plugins/woocommerce-admin/package-lock.json
+++ b/plugins/woocommerce-admin/package-lock.json
@@ -3646,6 +3646,15 @@
}
}
},
+ "@storybook/addon-console": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-console/-/addon-console-1.2.1.tgz",
+ "integrity": "sha512-2iDbDTipWonvRpIqLLntfhCGvawFFvoG1xyErpyL7K/HRdQ1zzIvR1Qm83S7TK8Vg+RzZWm4wcDbxx7WOsFCNg==",
+ "dev": true,
+ "requires": {
+ "global": "^4.3.2"
+ }
+ },
"@storybook/addon-docs": {
"version": "5.3.18",
"resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-5.3.18.tgz",
@@ -5313,6 +5322,12 @@
"@types/testing-library__react": "^10.0.0"
}
},
+ "@testing-library/user-event": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-10.1.0.tgz",
+ "integrity": "sha512-qutUm/2lWAD8IiKrss2Cg6Hf8AkcMeylKm09bSMtYC39Ug68aXWkcbc0H/NVD5R1zOHguTjkR/Ppuns6bWksGQ==",
+ "dev": true
+ },
"@types/anymatch": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
@@ -22203,7 +22218,7 @@
"dev": true
},
"prettier": {
- "version": "npm:wp-prettier@1.19.1",
+ "version": "npm: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==",
"dev": true
diff --git a/plugins/woocommerce-admin/package.json b/plugins/woocommerce-admin/package.json
index 45d9cfd5360..55c459206a0 100644
--- a/plugins/woocommerce-admin/package.json
+++ b/plugins/woocommerce-admin/package.json
@@ -145,6 +145,7 @@
"@octokit/graphql": "4.3.1",
"@storybook/addon-a11y": "5.3.18",
"@storybook/addon-actions": "5.3.18",
+ "@storybook/addon-console": "1.2.1",
"@storybook/addon-docs": "5.3.18",
"@storybook/addon-knobs": "5.3.18",
"@storybook/addon-links": "5.3.18",
@@ -153,6 +154,7 @@
"@storybook/addons": "5.3.18",
"@storybook/react": "5.3.18",
"@testing-library/react": "^10.0.3",
+ "@testing-library/user-event": "^10.1.0",
"@wordpress/babel-plugin-import-jsx-pragma": "1.1.3",
"@wordpress/babel-plugin-makepot": "2.1.3",
"@wordpress/babel-preset-default": "3.0.2",
diff --git a/plugins/woocommerce-admin/packages/components/src/link/stories/index.js b/plugins/woocommerce-admin/packages/components/src/link/stories/index.js
index 206f1910240..b5792fa5194 100644
--- a/plugins/woocommerce-admin/packages/components/src/link/stories/index.js
+++ b/plugins/woocommerce-admin/packages/components/src/link/stories/index.js
@@ -1,17 +1,62 @@
-/*
+/**
+ * External dependencies
+ */
+import { withConsole } from '@storybook/addon-console';
+
+/**
* Internal dependencies
*/
import Link from '../';
+function logLinkClick( event ) {
+ const a = event.currentTarget;
+ const logMessage = `[${ a.textContent }](${ a.href }) ${ a.dataset.linkType } link clicked`;
+
+ // eslint-disable-next-line no-console
+ console.log( logMessage );
+
+ event.preventDefault();
+ return false;
+}
+
export default {
title: 'WooCommerce Admin/components/Link',
component: Link,
+ decorators: [ ( storyFn, context ) => withConsole()( storyFn )( context ) ],
};
export const External = () => {
return (
-
+
WooCommerce.com
);
};
+
+export const WCAdmin = () => {
+ return (
+
+ Analytics: Orders
+
+ );
+};
+
+export const WPAdmin = () => {
+ return (
+
+ New Product
+
+ );
+};
diff --git a/plugins/woocommerce-admin/packages/components/src/link/test/index.js b/plugins/woocommerce-admin/packages/components/src/link/test/index.js
new file mode 100644
index 00000000000..a8512a9151c
--- /dev/null
+++ b/plugins/woocommerce-admin/packages/components/src/link/test/index.js
@@ -0,0 +1,124 @@
+/**
+ * External dependencies
+ */
+import { fireEvent, render } from '@testing-library/react';
+
+/**
+ * Internal dependencies
+ */
+import Link from '../index';
+
+describe( 'Link', () => {
+ it( 'should render `external` links', () => {
+ const { container } = render(
+
+ WooCommerce.com
+
+ );
+
+ expect( container.firstChild ).toMatchInlineSnapshot( `
+
+ WooCommerce.com
+
+ ` );
+ } );
+
+ it( 'should render `wp-admin` links', () => {
+ const { container } = render(
+
+ New Post
+
+ );
+
+ expect( container.firstChild ).toMatchInlineSnapshot( `
+
+ New Post
+
+ ` );
+ } );
+
+ it( 'should render `wc-admin` links', () => {
+ const { container } = render(
+
+ Analytics: Orders
+
+ );
+
+ expect( container.firstChild ).toMatchInlineSnapshot( `
+
+ Analytics: Orders
+
+ ` );
+ } );
+
+ it( 'should render links without a type as `wc-admin`', () => {
+ const { container } = render(
+
+ Analytics: Orders
+
+ );
+
+ expect( container.firstChild ).toMatchInlineSnapshot( `
+
+ Analytics: Orders
+
+ ` );
+ } );
+
+ it( 'should allow custom props to be passed through', () => {
+ const { container } = render(
+
+ WooCommerce.com
+
+ );
+
+ expect( container.firstChild ).toMatchInlineSnapshot( `
+
+ WooCommerce.com
+
+ ` );
+ } );
+
+ it( 'should support `onClick`', () => {
+ const clickHandler = jest.fn();
+
+ const { container } = render(
+
+ WooCommerce.com
+
+ );
+
+ fireEvent.click( container.firstChild );
+
+ expect( clickHandler ).toHaveBeenCalled();
+ } );
+} );
diff --git a/plugins/woocommerce-admin/packages/components/src/list/index.js b/plugins/woocommerce-admin/packages/components/src/list/index.js
index 5bebe52118a..a17d22a9c7a 100644
--- a/plugins/woocommerce-admin/packages/components/src/list/index.js
+++ b/plugins/woocommerce-admin/packages/components/src/list/index.js
@@ -21,6 +21,16 @@ class List extends Component {
}
}
+ getItemLinkType( item ) {
+ const { href, linkType } = item;
+
+ if ( linkType ) {
+ return linkType;
+ }
+
+ return href ? 'external' : null;
+ }
+
render() {
const { className, items } = this.props;
const listClassName = classnames( 'woocommerce-list', className );
@@ -34,6 +44,7 @@ class List extends Component {
className: itemClasses,
content,
href,
+ listItemTag,
onClick,
target,
title,
@@ -57,8 +68,9 @@ class List extends Component {
onKeyDown: ( e ) =>
hasAction ? this.handleKeyDown( e, onClick ) : null,
target: href ? target : null,
- type: href ? 'external' : null,
+ type: this.getItemLinkType( item ),
href,
+ 'data-list-item-tag': listItemTag,
};
return (
diff --git a/plugins/woocommerce-admin/packages/components/src/list/stories/index.js b/plugins/woocommerce-admin/packages/components/src/list/stories/index.js
index 2ae3bcbc311..3ce10fd3f5e 100644
--- a/plugins/woocommerce-admin/packages/components/src/list/stories/index.js
+++ b/plugins/woocommerce-admin/packages/components/src/list/stories/index.js
@@ -2,6 +2,7 @@
* External dependencies
*/
import Gridicon from 'gridicons';
+import { withConsole } from '@storybook/addon-console';
/**
* Internal dependencies
@@ -9,9 +10,27 @@ import Gridicon from 'gridicons';
import List from '../';
import './style.scss';
+function logItemClick( event ) {
+ const a = event.currentTarget;
+ const itemDescription = a.href
+ ? `[${ a.textContent }](${ a.href }) ${ a.dataset.linkType }`
+ : `[${ a.textContent }]`;
+ const itemTag = a.dataset.listItemTag
+ ? `'${ a.dataset.listItemTag }'`
+ : 'not set';
+ const logMessage = `[${ itemDescription } item clicked (tag: ${ itemTag })`;
+
+ // eslint-disable-next-line no-console
+ console.log( logMessage );
+
+ event.preventDefault();
+ return false;
+}
+
export default {
title: 'WooCommerce Admin/components/List',
component: List,
+ decorators: [ ( storyFn, context ) => withConsole()( storyFn )( context ) ],
};
export const Default = () => {
@@ -19,10 +38,12 @@ export const Default = () => {
{
title: 'WooCommerce.com',
href: 'https://woocommerce.com',
+ onClick: logItemClick,
},
{
title: 'WordPress.org',
href: 'https://wordpress.org',
+ onClick: logItemClick,
},
{
title: 'A list item with no action',
@@ -30,9 +51,10 @@ export const Default = () => {
{
title: 'Click me!',
content: 'An alert will be triggered.',
- onClick: () => {
+ onClick: ( event ) => {
// eslint-disable-next-line no-alert
window.alert( 'List item clicked' );
+ return logItemClick( event );
},
},
];
@@ -47,12 +69,14 @@ export const BeforeAndAfter = () => {
after: ,
title: 'WooCommerce.com',
href: 'https://woocommerce.com',
+ onClick: logItemClick,
},
{
before: ,
after: ,
title: 'WordPress.org',
href: 'https://wordpress.org',
+ onClick: logItemClick,
},
{
before: ,
@@ -63,9 +87,10 @@ export const BeforeAndAfter = () => {
before: ,
title: 'Click me!',
content: 'An alert will be triggered.',
- onClick: () => {
+ onClick: ( event ) => {
// eslint-disable-next-line no-alert
window.alert( 'List item clicked' );
+ return logItemClick( event );
},
},
];
@@ -73,19 +98,23 @@ export const BeforeAndAfter = () => {
return
;
};
-export const CustomStyle = () => {
+export const CustomStyleAndTags = () => {
const listItems = [
{
before: ,
after: ,
title: 'WooCommerce.com',
href: 'https://woocommerce.com',
+ onClick: logItemClick,
+ listItemTag: 'woocommerce.com-link',
},
{
before: ,
after: ,
title: 'WordPress.org',
href: 'https://wordpress.org',
+ onClick: logItemClick,
+ listItemTag: 'wordpress.org-link',
},
{
before: ,
@@ -95,10 +124,12 @@ export const CustomStyle = () => {
before: ,
title: 'Click me!',
content: 'An alert will be triggered.',
- onClick: () => {
+ onClick: ( event ) => {
// eslint-disable-next-line no-alert
window.alert( 'List item clicked' );
+ return logItemClick( event );
},
+ listItemTag: 'click-me',
},
];
diff --git a/plugins/woocommerce-admin/packages/components/src/list/test/index.js b/plugins/woocommerce-admin/packages/components/src/list/test/index.js
new file mode 100644
index 00000000000..3f57d756631
--- /dev/null
+++ b/plugins/woocommerce-admin/packages/components/src/list/test/index.js
@@ -0,0 +1,141 @@
+/**
+ * External dependencies
+ */
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+
+/**
+ * Internal dependencies
+ */
+import List from '../index';
+
+describe( 'List', () => {
+ it( 'should have aria roles for items', () => {
+ const clickHandler = jest.fn();
+ const listItems = [
+ {
+ title: 'WooCommerce.com',
+ href: 'https://woocommerce.com',
+ },
+ {
+ title: 'Click me!',
+ onClick: clickHandler,
+ },
+ ];
+
+ render(
);
+
+ expect( screen.getAllByRole( 'menuitem' ) ).toHaveLength( 2 );
+ } );
+
+ it( 'should support `onClick` for items', () => {
+ const clickHandler = jest.fn();
+ const listItems = [
+ {
+ title: 'WooCommerce.com',
+ href: 'https://woocommerce.com',
+ },
+ {
+ title: 'Click me!',
+ onClick: clickHandler,
+ },
+ ];
+
+ render(
);
+
+ userEvent.click(
+ screen.getByRole( 'menuitem', { name: 'Click me!' } )
+ );
+
+ expect( clickHandler ).toHaveBeenCalled();
+ } );
+
+ it( 'should set `data-link-type` on items', () => {
+ const listItems = [
+ {
+ title: 'Add products',
+ href: '/post-new.php?post_type=product',
+ linkType: 'wp-admin',
+ },
+ {
+ title: 'Market my store',
+ href: '/admin.php?page=wc-admin&path=%2Fmarketing',
+ linkType: 'wc-admin',
+ },
+ {
+ title: 'WooCommerce.com',
+ href: 'https://woocommerce.com',
+ linkType: 'external',
+ },
+ {
+ title: 'WordPress.org',
+ href: 'https://wordpress.org',
+ },
+ ];
+
+ render(
);
+
+ expect(
+ screen.getByRole( 'menuitem', { name: 'Add products' } ).dataset
+ .linkType
+ ).toBe( 'wp-admin' );
+ expect(
+ screen.getByRole( 'menuitem', { name: 'Market my store' } ).dataset
+ .linkType
+ ).toBe( 'wc-admin' );
+ expect(
+ screen.getByRole( 'menuitem', { name: 'WooCommerce.com' } ).dataset
+ .linkType
+ ).toBe( 'external' );
+ expect(
+ screen.getByRole( 'menuitem', { name: 'WordPress.org' } ).dataset
+ .linkType
+ ).toBe( 'external' );
+ } );
+
+ it( 'should set `data-list-item-tag` on items', () => {
+ const listItems = [
+ {
+ title: 'Add products',
+ href: '/post-new.php?post_type=product',
+ linkType: 'wp-admin',
+ listItemTag: 'add-product',
+ },
+ {
+ title: 'Market my store',
+ href: '/admin.php?page=wc-admin&path=%2Fmarketing',
+ linkType: 'wc-admin',
+ listItemTag: 'marketing',
+ },
+ {
+ title: 'WooCommerce.com',
+ href: 'https://woocommerce.com',
+ linkType: 'external',
+ listItemTag: 'woocommerce.com-site',
+ },
+ {
+ title: 'WordPress.org',
+ href: 'https://wordpress.org',
+ },
+ ];
+
+ render(
);
+
+ expect(
+ screen.getByRole( 'menuitem', { name: 'Add products' } ).dataset
+ .listItemTag
+ ).toBe( 'add-product' );
+ expect(
+ screen.getByRole( 'menuitem', { name: 'Market my store' } ).dataset
+ .listItemTag
+ ).toBe( 'marketing' );
+ expect(
+ screen.getByRole( 'menuitem', { name: 'WooCommerce.com' } ).dataset
+ .listItemTag
+ ).toBe( 'woocommerce.com-site' );
+ expect(
+ screen.getByRole( 'menuitem', { name: 'WordPress.org' } ).dataset
+ .listItemTag
+ ).toBeUndefined();
+ } );
+} );