Skip to content

Commit cc04074

Browse files
committed
Components: Implement Button as assigning ref via forwardRef
1 parent c259e30 commit cc04074

File tree

4 files changed

+78
-59
lines changed

4 files changed

+78
-59
lines changed

components/button/index.js

Lines changed: 36 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,67 +6,47 @@ import classnames from 'classnames';
66
/**
77
* WordPress dependencies
88
*/
9-
import { Component, createElement } from '@wordpress/element';
9+
import { createElement, forwardRef } from '@wordpress/element';
1010

1111
/**
1212
* Internal dependencies
1313
*/
1414
import './style.scss';
1515

16-
class Button extends Component {
17-
constructor( props ) {
18-
super( props );
19-
this.setRef = this.setRef.bind( this );
20-
}
21-
22-
componentDidMount() {
23-
if ( this.props.focus ) {
24-
this.ref.focus();
25-
}
26-
}
27-
28-
setRef( ref ) {
29-
this.ref = ref;
30-
}
31-
32-
focus() {
33-
this.ref.focus();
34-
}
35-
36-
render() {
37-
const {
38-
href,
39-
target,
40-
isPrimary,
41-
isLarge,
42-
isSmall,
43-
isToggled,
44-
isBusy,
45-
className,
46-
disabled,
47-
...additionalProps
48-
} = this.props;
49-
const classes = classnames( 'components-button', className, {
50-
button: ( isPrimary || isLarge || isSmall ),
51-
'button-primary': isPrimary,
52-
'button-large': isLarge,
53-
'button-small': isSmall,
54-
'is-toggled': isToggled,
55-
'is-busy': isBusy,
56-
} );
57-
58-
const tag = href !== undefined && ! disabled ? 'a' : 'button';
59-
const tagProps = tag === 'a' ? { href, target } : { type: 'button', disabled };
60-
61-
delete additionalProps.focus;
62-
63-
return createElement( tag, {
64-
...tagProps,
65-
...additionalProps,
66-
className: classes,
67-
ref: this.setRef,
68-
} );
69-
}
16+
export function Button( props, ref ) {
17+
const {
18+
href,
19+
target,
20+
isPrimary,
21+
isLarge,
22+
isSmall,
23+
isToggled,
24+
isBusy,
25+
className,
26+
disabled,
27+
focus,
28+
...additionalProps
29+
} = props;
30+
31+
const classes = classnames( 'components-button', className, {
32+
button: ( isPrimary || isLarge || isSmall ),
33+
'button-primary': isPrimary,
34+
'button-large': isLarge,
35+
'button-small': isSmall,
36+
'is-toggled': isToggled,
37+
'is-busy': isBusy,
38+
} );
39+
40+
const tag = href !== undefined && ! disabled ? 'a' : 'button';
41+
const tagProps = tag === 'a' ? { href, target } : { type: 'button', disabled };
42+
43+
return createElement( tag, {
44+
...tagProps,
45+
...additionalProps,
46+
className: classes,
47+
autoFocus: focus,
48+
ref,
49+
} );
7050
}
7151

72-
export default Button;
52+
export default forwardRef( Button );

components/button/test/index.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
/**
22
* External dependencies
33
*/
4-
import { shallow } from 'enzyme';
4+
import { mount, shallow } from 'enzyme';
5+
6+
/**
7+
* WordPress dependencies
8+
*/
9+
import { createRef } from '@wordpress/element';
510

611
/**
712
* Internal dependencies
813
*/
9-
import Button from '../';
14+
import ButtonWithForwardedRef, { Button } from '../';
15+
16+
// [TEMPORARY]: Only needed so long as Enzyme does not support React.forwardRef
17+
jest.unmock( '../' );
1018

1119
describe( 'Button', () => {
1220
describe( 'basic rendering', () => {
@@ -93,4 +101,18 @@ describe( 'Button', () => {
93101
expect( button.type() ).toBe( 'button' );
94102
} );
95103
} );
104+
105+
// Disable reason: This test is desirable, but unsupported by Enzyme in
106+
// the current version, as it depends on features new to React in 16.3.0.
107+
//
108+
// eslint-disable-next-line jest/no-disabled-tests
109+
describe.skip( 'ref forwarding', () => {
110+
it( 'should enable access to DOM element', () => {
111+
const ref = createRef();
112+
113+
mount( <ButtonWithForwardedRef ref={ ref } /> );
114+
115+
expect( ref.current.nodeName ).toBe( 'button' );
116+
} );
117+
} );
96118
} );

test/unit/jest.config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
"setupFiles": [
1111
"core-js/fn/symbol/async-iterator",
1212
"<rootDir>/test/unit/setup-blocks.js",
13-
"<rootDir>/test/unit/setup-wp-aliases.js"
13+
"<rootDir>/test/unit/setup-wp-aliases.js",
14+
"<rootDir>/test/unit/setup-mocks.js"
1415
],
1516
"transform": {
1617
"\\.pegjs$": "<rootDir>/test/unit/pegjs-transform.js"

test/unit/setup-mocks.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// [TEMPORARY]: Button uses React.forwardRef, added in [email protected] but not yet
2+
// supported by Enzyme as of [email protected] . This mock unwraps
3+
// the ref forwarding, so any tests relying on this behavior will fail.
4+
//
5+
// See: https://github.com/airbnb/enzyme/issues/1604
6+
// See: https://github.com/airbnb/enzyme/pull/1592/files
7+
jest.mock( '../../components/button', () => {
8+
const { Button: RawButton } = require.requireActual( '../../components/button' );
9+
const { Component } = require( 'react' );
10+
11+
return class Button extends Component {
12+
render() {
13+
return RawButton( this.props );
14+
}
15+
};
16+
} );

0 commit comments

Comments
 (0)