From 7e629aa9fdf9f20cb4c1bf082293710b42625157 Mon Sep 17 00:00:00 2001
From: Marin Atanasov
Date: Thu, 4 Aug 2022 16:06:42 +0300
Subject: [PATCH 1/4] Components: Refactor Button tests to
@testing-library/react
---
packages/components/src/button/test/index.js | 304 ++++++++++---------
1 file changed, 168 insertions(+), 136 deletions(-)
diff --git a/packages/components/src/button/test/index.js b/packages/components/src/button/test/index.js
index 9d2b9f5383ceab..b0248f48d0388c 100644
--- a/packages/components/src/button/test/index.js
+++ b/packages/components/src/button/test/index.js
@@ -1,8 +1,9 @@
/**
* External dependencies
*/
-import { shallow } from 'enzyme';
+import { render, screen } from '@testing-library/react';
import TestUtils from 'react-dom/test-utils';
+
/**
* WordPress dependencies
*/
@@ -12,172 +13,197 @@ import { plusCircle } from '@wordpress/icons';
/**
* Internal dependencies
*/
-import ButtonWithForwardedRef, { Button } from '../';
-import { VisuallyHidden } from '../../visually-hidden';
+import Button from '../';
+
+jest.mock( '../../icon', () => () => );
+jest.mock( '../../tooltip', () => ( { text, children } ) => (
+
+ { children }
+
+) );
+jest.mock( '../../visually-hidden', () => ( {
+ __esModule: true,
+ VisuallyHidden: ( { children } ) => (
+ { children }
+ ),
+} ) );
describe( 'Button', () => {
describe( 'basic rendering', () => {
it( 'should render a button element with only one class', () => {
- const button = shallow( ).find( 'button' );
- expect( button.hasClass( 'components-button' ) ).toBe( true );
- expect( button.hasClass( 'is-large' ) ).toBe( false );
- expect( button.hasClass( 'is-primary' ) ).toBe( false );
- expect( button.hasClass( 'is-pressed' ) ).toBe( false );
- expect( button.prop( 'disabled' ) ).toBeUndefined();
- expect( button.prop( 'aria-disabled' ) ).toBeUndefined();
- expect( button.prop( 'type' ) ).toBe( 'button' );
- expect( button.type() ).toBe( 'button' );
+ const button = render( ).container.firstChild;
+
+ expect( button ).toHaveClass( 'components-button' );
+ expect( button ).not.toHaveClass( 'is-large' );
+ expect( button ).not.toHaveClass( 'is-primary' );
+ expect( button ).not.toHaveClass( 'is-pressed' );
+ expect( button ).not.toHaveAttribute( 'disabled' );
+ expect( button ).not.toHaveAttribute( 'aria-disabled' );
+ expect( button ).toHaveAttribute( 'type', 'button' );
+ expect( button.tagName ).toBe( 'BUTTON' );
} );
it( 'should render a button element with is-primary class', () => {
- const button = shallow( ).find(
- 'button'
- );
- expect( button.hasClass( 'is-large' ) ).toBe( false );
- expect( button.hasClass( 'is-primary' ) ).toBe( true );
+ const button = render( ).container
+ .firstChild;
+
+ expect( button ).not.toHaveClass( 'is-large' );
+ expect( button ).toHaveClass( 'is-primary' );
} );
it( 'should render a button element with is-secondary and is-small class', () => {
- const button = shallow(
-
- ).find( 'button' );
- expect( button.hasClass( 'is-secondary' ) ).toBe( true );
- expect( button.hasClass( 'is-large' ) ).toBe( false );
- expect( button.hasClass( 'is-small' ) ).toBe( true );
- expect( button.hasClass( 'is-primary' ) ).toBe( false );
+ const button = render( )
+ .container.firstChild;
+
+ expect( button ).toHaveClass( 'is-secondary' );
+ expect( button ).not.toHaveClass( 'is-large' );
+ expect( button ).toHaveClass( 'is-small' );
+ expect( button ).not.toHaveClass( 'is-primary' );
} );
it( 'should render a button element with is-tertiary class', () => {
- const button = shallow( ).find(
- 'button'
- );
- expect( button.hasClass( 'is-large' ) ).toBe( false );
- expect( button.hasClass( 'is-primary' ) ).toBe( false );
- expect( button.hasClass( 'is-secondary' ) ).toBe( false );
- expect( button.hasClass( 'is-tertiary' ) ).toBe( true );
+ const button = render( ).container
+ .firstChild;
+
+ expect( button ).not.toHaveClass( 'is-large' );
+ expect( button ).not.toHaveClass( 'is-primary' );
+ expect( button ).not.toHaveClass( 'is-secondary' );
+ expect( button ).toHaveClass( 'is-tertiary' );
} );
it( 'should render a button element with is-link class', () => {
- const button = shallow( ).find(
- 'button'
- );
- expect( button.hasClass( 'is-primary' ) ).toBe( false );
- expect( button.hasClass( 'is-secondary' ) ).toBe( false );
- expect( button.hasClass( 'is-tertiary' ) ).toBe( false );
- expect( button.hasClass( 'is-link' ) ).toBe( true );
+ const button = render( ).container
+ .firstChild;
+
+ expect( button ).not.toHaveClass( 'is-primary' );
+ expect( button ).not.toHaveClass( 'is-secondary' );
+ expect( button ).not.toHaveClass( 'is-tertiary' );
+ expect( button ).toHaveClass( 'is-link' );
} );
it( 'should render a button element with is-pressed without button class', () => {
- const button = shallow( ).find( 'button' );
- expect( button.hasClass( 'is-pressed' ) ).toBe( true );
+ const button = render( ).container.firstChild;
+
+ expect( button ).toHaveClass( 'is-pressed' );
} );
it( 'should add a disabled prop to the button', () => {
- const button = shallow( ).find( 'button' );
- expect( button.prop( 'disabled' ) ).toBe( true );
+ const button = render( ).container.firstChild;
+
+ expect( button ).toHaveAttribute( 'disabled' );
} );
it( 'should add only aria-disabled attribute when disabled and isFocusable are true', () => {
- const button = shallow(
+ const button = render(
- ).find( 'button' );
- expect( button.prop( 'disabled' ) ).toBe( false );
- expect( button.prop( 'aria-disabled' ) ).toBe( true );
+ ).container.firstChild;
+
+ expect( button ).not.toHaveAttribute( 'disabled' );
+ expect( button ).toHaveAttribute( 'aria-disabled' );
} );
- it( 'should not poss the prop target into the element', () => {
- const button = shallow( ).find(
- 'button'
- );
- expect( button.prop( 'target' ) ).toBeUndefined();
+ it( 'should not pass the prop target into the element', () => {
+ const button = render( ).container
+ .firstChild;
+
+ expect( button ).not.toHaveAttribute( 'target' );
} );
it( 'should render with an additional className', () => {
- const button = shallow( ).find(
- 'button'
- );
+ const button = render( ).container
+ .firstChild;
- expect( button.hasClass( 'gutenberg' ) ).toBe( true );
+ expect( button ).toHaveClass( 'gutenberg' );
} );
- it( 'should render and additional WordPress prop of value awesome', () => {
- const button = shallow( ).find(
- 'button'
- );
+ it( 'should render an additional WordPress prop of value awesome', () => {
+ const button = render( ).container
+ .firstChild;
- expect( button.prop( 'WordPress' ) ).toBe( 'awesome' );
+ expect( console ).toHaveErrored();
+ expect( button ).toHaveAttribute( 'wordpress', 'awesome' );
} );
it( 'should render an icon button', () => {
- const iconButton = shallow( ).find(
- 'button'
- );
- expect( iconButton.hasClass( 'has-icon' ) ).toBe( true );
- expect( iconButton.prop( 'aria-label' ) ).toBeUndefined();
+ const button = render( ).container
+ .firstChild;
+
+ expect( button ).toHaveClass( 'has-icon' );
+ expect( button ).not.toHaveAttribute( 'aria-label' );
} );
it( 'should render a Dashicon component matching the wordpress icon', () => {
- const iconButton = shallow( ).find(
- 'button'
+ const button = render( ).container
+ .firstChild;
+
+ expect( button ).toContainElement(
+ screen.getByTestId( 'test-icon' )
);
- expect( iconButton.find( 'Icon' ).dive() ).not.toBeNull();
} );
it( 'should render child elements and icon', () => {
- const iconButton = shallow(
+ const button = render(
}
/>
- ).find( 'button' );
- expect( iconButton.find( 'Icon' ).dive() ).not.toBeNull();
- expect( iconButton.find( '.test' ).shallow().text() ).toBe(
- 'Test'
+ ).container.firstChild;
+
+ expect( button ).toContainElement(
+ screen.getByTestId( 'test-icon' )
);
+
+ const paragraph = button.childNodes[ 1 ];
+ expect( paragraph ).toHaveClass( 'test' );
+ expect( paragraph ).toHaveTextContent( 'Test' );
} );
it( 'should add an aria-label when the label property is used, with Tooltip wrapper', () => {
- const iconButton = shallow(
-
- ).find( 'Tooltip' );
- expect( iconButton.name() ).toBe( 'Tooltip' );
- expect( iconButton.prop( 'text' ) ).toBe( 'WordPress' );
- expect( iconButton.find( 'button' ).prop( 'aria-label' ) ).toBe(
- 'WordPress'
- );
+ render( );
+
+ const tooltip = screen.getByTestId( 'test-tooltip' );
+ expect( tooltip ).toBeVisible();
+ expect( tooltip ).toHaveAttribute( 'title', 'WordPress' );
+
+ const button = screen.getByRole( 'button' );
+ expect( tooltip ).toContainElement( button );
+ expect( button ).toHaveAttribute( 'aria-label', 'WordPress' );
} );
it( 'should support explicit aria-label override', () => {
- const iconButton = shallow( ).find(
- 'button'
- );
- expect( iconButton.prop( 'aria-label' ) ).toBe( 'Custom' );
+ const button = render( ).container
+ .firstChild;
+
+ expect( button ).toHaveAttribute( 'aria-label', 'Custom' );
} );
it( 'should support adding aria-describedby text', () => {
- const buttonDescription = shallow(
-
- )
- .find( VisuallyHidden )
- .shallow()
- .text();
- expect( buttonDescription ).toBe( 'Description text' );
+ const button = render( )
+ .container.firstChild;
+
+ expect( button ).toHaveAttribute( 'aria-describedby' );
+ expect(
+ screen.getByTestId( 'test-visually-hidden' )
+ ).toHaveTextContent( 'Description text' );
} );
it( 'should populate tooltip with label content for buttons without visible labels (no children)', () => {
- const buttonTooltip = shallow(
+ render(
- ).find( 'Tooltip' );
+ );
- expect( buttonTooltip.prop( 'text' ) ).toBe( 'Label' );
+ expect( screen.getByTestId( 'test-tooltip' ) ).toHaveAttribute(
+ 'title',
+ 'Label'
+ );
} );
it( 'should populate tooltip with description content for buttons with visible labels (buttons with children)', () => {
- const buttonTooltip = shallow(
+ render(
- ).find( 'Tooltip' );
+ );
- expect( buttonTooltip.prop( 'text' ) ).toBe( 'Description text' );
+ expect( screen.getByTestId( 'test-tooltip' ) ).toHaveAttribute(
+ 'title',
+ 'Description text'
+ );
} );
it( 'should allow tooltip disable', () => {
- const iconButton = shallow(
+ const button = render(
- ).find( 'button' );
- expect( iconButton.name() ).toBe( 'button' );
- expect( iconButton.prop( 'aria-label' ) ).toBe( 'WordPress' );
+ ).container.firstChild;
+
+ expect( button.tagName ).toBe( 'BUTTON' );
+ expect( button ).toHaveAttribute( 'aria-label', 'WordPress' );
} );
it( 'should show the tooltip for empty children', () => {
- const iconButton = shallow(
+ const tooltip = render(
- ).find( 'Tooltip' );
- expect( iconButton.name() ).toBe( 'Tooltip' );
- expect( iconButton.prop( 'text' ) ).toBe( 'WordPress' );
+ ).container.firstChild;
+
+ expect( tooltip ).toBe( screen.getByTestId( 'test-tooltip' ) );
+ expect( tooltip ).toHaveAttribute( 'title', 'WordPress' );
} );
it( 'should not show the tooltip when icon and children defined', () => {
- const iconButton = shallow(
+ const button = render(
- ).find( 'button' );
- expect( iconButton.name() ).toBe( 'button' );
+ ).container.firstChild;
+
+ expect( button.tagName ).toBe( 'BUTTON' );
} );
it( 'should force showing the tooltip even if icon and children defined', () => {
- const iconButton = shallow(
+ const tooltip = render(
- ).find( 'Tooltip' );
- expect( iconButton.name() ).toBe( 'Tooltip' );
+ ).container.firstChild;
+
+ expect( tooltip ).toBe( screen.getByTestId( 'test-tooltip' ) );
} );
} );
describe( 'with href property', () => {
it( 'should render a link instead of a button with href prop', () => {
- const button = shallow(
-
- ).find( 'a' );
+ const link = render( )
+ .container.firstChild;
- expect( button.type() ).toBe( 'a' );
- expect( button.prop( 'href' ) ).toBe( 'https://wordpress.org/' );
+ expect( link.tagName ).toBe( 'A' );
+ expect( link ).toHaveAttribute( 'href', 'https://wordpress.org/' );
} );
it( 'should allow for the passing of the target prop when a link is created', () => {
- const button = shallow(
+ const link = render(
- ).find( 'a' );
+ ).container.firstChild;
- expect( button.prop( 'target' ) ).toBe( '_blank' );
+ expect( link ).toHaveAttribute( 'target', '_blank' );
} );
it( 'should become a button again when disabled is supplied', () => {
- const button = shallow(
+ const button = render(
- ).find( 'button' );
+ ).container.firstChild;
- expect( button.type() ).toBe( 'button' );
+ expect( button.tagName ).toBe( 'BUTTON' );
} );
} );
@@ -261,37 +293,37 @@ describe( 'Button', () => {
it( 'should enable access to DOM element', () => {
const ref = createRef();
- TestUtils.renderIntoDocument(
-
- );
+ TestUtils.renderIntoDocument( );
+
expect( ref.current.type ).toBe( 'button' );
} );
} );
describe( 'deprecated props', () => {
it( 'should not break when the legacy isPrimary prop is passed', () => {
- const button = shallow( ).find( 'button' );
- expect( button.hasClass( 'is-primary' ) ).toBe( true );
+ const button = render( ).container.firstChild;
+ expect( button ).toHaveClass( 'is-primary' );
} );
it( 'should not break when the legacy isSecondary prop is passed', () => {
- const button = shallow( ).find( 'button' );
- expect( button.hasClass( 'is-secondary' ) ).toBe( true );
+ const button = render( ).container
+ .firstChild;
+ expect( button ).toHaveClass( 'is-secondary' );
} );
it( 'should not break when the legacy isTertiary prop is passed', () => {
- const button = shallow( ).find( 'button' );
- expect( button.hasClass( 'is-tertiary' ) ).toBe( true );
+ const button = render( ).container.firstChild;
+ expect( button ).toHaveClass( 'is-tertiary' );
} );
it( 'should not break when the legacy isLink prop is passed', () => {
- const button = shallow( ).find( 'button' );
- expect( button.hasClass( 'is-link' ) ).toBe( true );
+ const button = render( ).container.firstChild;
+ expect( button ).toHaveClass( 'is-link' );
} );
it( 'should warn when the isDefault prop is passed', () => {
- const button = shallow( ).find( 'button' );
- expect( button.hasClass( 'is-secondary' ) ).toBe( true );
+ const button = render( ).container.firstChild;
+ expect( button ).toHaveClass( 'is-secondary' );
expect( console ).toHaveWarned();
} );
From da7aa9c9196679e458d885b586e70cab4a9276b2 Mon Sep 17 00:00:00 2001
From: Marin Atanasov
Date: Wed, 10 Aug 2022 09:51:28 +0300
Subject: [PATCH 2/4] Always use screen.getByRole queries
---
packages/components/src/button/test/index.js | 90 +++++++++++---------
1 file changed, 49 insertions(+), 41 deletions(-)
diff --git a/packages/components/src/button/test/index.js b/packages/components/src/button/test/index.js
index b0248f48d0388c..71d76afe57906b 100644
--- a/packages/components/src/button/test/index.js
+++ b/packages/components/src/button/test/index.js
@@ -31,7 +31,8 @@ jest.mock( '../../visually-hidden', () => ( {
describe( 'Button', () => {
describe( 'basic rendering', () => {
it( 'should render a button element with only one class', () => {
- const button = render( ).container.firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).toHaveClass( 'components-button' );
expect( button ).not.toHaveClass( 'is-large' );
@@ -40,20 +41,19 @@ describe( 'Button', () => {
expect( button ).not.toHaveAttribute( 'disabled' );
expect( button ).not.toHaveAttribute( 'aria-disabled' );
expect( button ).toHaveAttribute( 'type', 'button' );
- expect( button.tagName ).toBe( 'BUTTON' );
} );
it( 'should render a button element with is-primary class', () => {
- const button = render( ).container
- .firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).not.toHaveClass( 'is-large' );
expect( button ).toHaveClass( 'is-primary' );
} );
it( 'should render a button element with is-secondary and is-small class', () => {
- const button = render( )
- .container.firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).toHaveClass( 'is-secondary' );
expect( button ).not.toHaveClass( 'is-large' );
@@ -62,8 +62,8 @@ describe( 'Button', () => {
} );
it( 'should render a button element with is-tertiary class', () => {
- const button = render( ).container
- .firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).not.toHaveClass( 'is-large' );
expect( button ).not.toHaveClass( 'is-primary' );
@@ -72,8 +72,8 @@ describe( 'Button', () => {
} );
it( 'should render a button element with is-link class', () => {
- const button = render( ).container
- .firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).not.toHaveClass( 'is-primary' );
expect( button ).not.toHaveClass( 'is-secondary' );
@@ -82,59 +82,60 @@ describe( 'Button', () => {
} );
it( 'should render a button element with is-pressed without button class', () => {
- const button = render( ).container.firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).toHaveClass( 'is-pressed' );
} );
it( 'should add a disabled prop to the button', () => {
- const button = render( ).container.firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).toHaveAttribute( 'disabled' );
} );
it( 'should add only aria-disabled attribute when disabled and isFocusable are true', () => {
- const button = render(
-
- ).container.firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).not.toHaveAttribute( 'disabled' );
expect( button ).toHaveAttribute( 'aria-disabled' );
} );
it( 'should not pass the prop target into the element', () => {
- const button = render( ).container
- .firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).not.toHaveAttribute( 'target' );
} );
it( 'should render with an additional className', () => {
- const button = render( ).container
- .firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).toHaveClass( 'gutenberg' );
} );
it( 'should render an additional WordPress prop of value awesome', () => {
- const button = render( ).container
- .firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( console ).toHaveErrored();
expect( button ).toHaveAttribute( 'wordpress', 'awesome' );
} );
it( 'should render an icon button', () => {
- const button = render( ).container
- .firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).toHaveClass( 'has-icon' );
expect( button ).not.toHaveAttribute( 'aria-label' );
} );
it( 'should render a Dashicon component matching the wordpress icon', () => {
- const button = render( ).container
- .firstChild;
+ render( );
+ const button = screen.getByRole( 'button' );
expect( button ).toContainElement(
screen.getByTestId( 'test-icon' )
@@ -142,12 +143,13 @@ describe( 'Button', () => {
} );
it( 'should render child elements and icon', () => {
- const button = render(
+ render(