Skip to content

Commit bca17b7

Browse files
eps1lonljharb
authored andcommitted
Add failing test case for refs on the root in mount
Fix ref on root component pointing to wrapper Backport root ref fix to older adapters Adjust ref call to work with 0.13 host instances Use ref prop type Check if WrapperComponent supports forwardedRef prop
1 parent 696a272 commit bca17b7

File tree

10 files changed

+51
-18
lines changed

10 files changed

+51
-18
lines changed

packages/enzyme-adapter-react-13/src/ReactThirteenAdapter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,16 @@ class ReactThirteenAdapter extends EnzymeAdapter {
125125
render(el, context, callback) {
126126
if (instance === null) {
127127
const { ref, type, props } = el;
128+
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
129+
const refProp = ReactWrapperComponent.supportsForwardedRef === true
130+
? 'forwardedRef'
131+
: 'ref';
128132
const wrapperProps = {
129133
Component: type,
130134
props,
131135
context,
132-
...(ref && { ref }),
136+
...(ref && { [refProp]: ref }),
133137
};
134-
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
135138
const wrappedEl = React.createElement(ReactWrapperComponent, wrapperProps);
136139
instance = React.render(wrappedEl, domNode);
137140
if (typeof callback === 'function') {

packages/enzyme-adapter-react-14/src/ReactFourteenAdapter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,17 @@ class ReactFourteenAdapter extends EnzymeAdapter {
105105
render(el, context, callback) {
106106
if (instance === null) {
107107
const { type, props, ref } = el;
108+
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
109+
const refProp = ReactWrapperComponent.supportsForwardedRef === true
110+
? 'forwardedRef'
111+
: 'ref';
108112
const wrapperProps = {
109113
Component: type,
110114
wrappingComponentProps: options.wrappingComponentProps,
111115
props,
112116
context,
113-
...(ref && { refProp: ref }),
117+
...(ref && { [refProp]: ref }),
114118
};
115-
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
116119
const wrappedEl = React.createElement(ReactWrapperComponent, wrapperProps);
117120
instance = ReactDOM.render(wrappedEl, domNode);
118121
if (typeof callback === 'function') {

packages/enzyme-adapter-react-15.4/src/ReactFifteenFourAdapter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,17 @@ class ReactFifteenFourAdapter extends EnzymeAdapter {
140140
render(el, context, callback) {
141141
if (instance === null) {
142142
const { type, props, ref } = el;
143+
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
144+
const refProp = ReactWrapperComponent.supportsForwardedRef === true
145+
? 'forwardedRef'
146+
: 'ref';
143147
const wrapperProps = {
144148
Component: type,
145149
wrappingComponentProps: options.wrappingComponentProps,
146150
props,
147151
context,
148-
...(ref && { refProp: ref }),
152+
...(ref && { [refProp]: ref }),
149153
};
150-
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
151154
const wrappedEl = React.createElement(ReactWrapperComponent, wrapperProps);
152155
instance = ReactDOM.render(wrappedEl, domNode);
153156
if (typeof callback === 'function') {

packages/enzyme-adapter-react-15/src/ReactFifteenAdapter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,17 @@ class ReactFifteenAdapter extends EnzymeAdapter {
140140
render(el, context, callback) {
141141
if (instance === null) {
142142
const { type, props, ref } = el;
143+
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
144+
const refProp = ReactWrapperComponent.supportsForwardedRef === true
145+
? 'forwardedRef'
146+
: 'ref';
143147
const wrapperProps = {
144148
Component: type,
145149
wrappingComponentProps: options.wrappingComponentProps,
146150
props,
147151
context,
148-
...(ref && { refProp: ref }),
152+
...(ref && { [refProp]: ref }),
149153
};
150-
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
151154
const wrappedEl = React.createElement(ReactWrapperComponent, wrapperProps);
152155
instance = ReactDOM.render(wrappedEl, domNode);
153156
if (typeof callback === 'function') {

packages/enzyme-adapter-react-16.1/src/ReactSixteenOneAdapter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,14 +273,17 @@ class ReactSixteenOneAdapter extends EnzymeAdapter {
273273
render(el, context, callback) {
274274
if (instance === null) {
275275
const { type, props, ref } = el;
276+
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
277+
const refProp = ReactWrapperComponent.supportsForwardedRef === true
278+
? 'forwardedRef'
279+
: 'ref';
276280
const wrapperProps = {
277281
Component: type,
278282
props,
279283
wrappingComponentProps,
280284
context,
281-
...(ref && { refProp: ref }),
285+
...(ref && { [refProp]: ref }),
282286
};
283-
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
284287
const wrappedEl = React.createElement(ReactWrapperComponent, wrapperProps);
285288
instance = hydrateIn
286289
? ReactDOM.hydrate(wrappedEl, domNode)

packages/enzyme-adapter-react-16.2/src/ReactSixteenTwoAdapter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,14 +275,17 @@ class ReactSixteenTwoAdapter extends EnzymeAdapter {
275275
render(el, context, callback) {
276276
if (instance === null) {
277277
const { type, props, ref } = el;
278+
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
279+
const refProp = ReactWrapperComponent.supportsForwardedRef === true
280+
? 'forwardedRef'
281+
: 'ref';
278282
const wrapperProps = {
279283
Component: type,
280284
props,
281285
wrappingComponentProps,
282286
context,
283-
...(ref && { refProp: ref }),
287+
...(ref && { [refProp]: ref }),
284288
};
285-
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
286289
const wrappedEl = React.createElement(ReactWrapperComponent, wrapperProps);
287290
instance = hydrateIn
288291
? ReactDOM.hydrate(wrappedEl, domNode)

packages/enzyme-adapter-react-16.3/src/ReactSixteenThreeAdapter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,17 @@ class ReactSixteenThreeAdapter extends EnzymeAdapter {
294294
render(el, context, callback) {
295295
if (instance === null) {
296296
const { type, props, ref } = el;
297+
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
298+
const refProp = ReactWrapperComponent.supportsForwardedRef === true
299+
? 'forwardedRef'
300+
: 'ref';
297301
const wrapperProps = {
298302
Component: type,
299303
props,
300304
wrappingComponentProps,
301305
context,
302-
...(ref && { refProp: ref }),
306+
...(ref && { [refProp]: ref }),
303307
};
304-
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
305308
const wrappedEl = React.createElement(ReactWrapperComponent, wrapperProps);
306309
instance = hydrateIn
307310
? ReactDOM.hydrate(wrappedEl, domNode)

packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,14 +423,17 @@ class ReactSixteenAdapter extends EnzymeAdapter {
423423
return wrapAct(() => {
424424
if (instance === null) {
425425
const { type, props, ref } = el;
426+
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
427+
const refProp = ReactWrapperComponent.supportsForwardedRef === true
428+
? 'forwardedRef'
429+
: 'ref';
426430
const wrapperProps = {
427431
Component: type,
428432
props,
429433
wrappingComponentProps,
430434
context,
431-
...(ref && { refProp: ref }),
435+
...(ref && { [refProp]: ref }),
432436
};
433-
const ReactWrapperComponent = createMountWrapper(el, { ...options, adapter });
434437
const wrappedEl = React.createElement(ReactWrapperComponent, wrapperProps);
435438
instance = hydrateIn
436439
? ReactDOM.hydrate(wrappedEl, domNode)

packages/enzyme-adapter-utils/src/createMountWrapper.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ export default function createMountWrapper(node, options = {}) {
6969
}
7070

7171
render() {
72-
const { Component, refProp } = this.props;
72+
const { Component, forwardedRef } = this.props;
7373
const { mount, props, wrappingComponentProps } = this.state;
7474
if (!mount) return null;
7575
// eslint-disable-next-line react/jsx-props-no-spreading
76-
const component = <Component ref={refProp} {...props} />;
76+
const component = <Component ref={forwardedRef} {...props} />;
7777
if (WrappingComponent) {
7878
return (
7979
// eslint-disable-next-line react/jsx-props-no-spreading
@@ -85,17 +85,20 @@ export default function createMountWrapper(node, options = {}) {
8585
return component;
8686
}
8787
}
88+
WrapperComponent.supportsForwardedRef = true;
8889
WrapperComponent.propTypes = {
8990
Component: makeValidElementType(adapter).isRequired,
9091
refProp: PropTypes.oneOfType([PropTypes.string, ref()]),
9192
props: PropTypes.object.isRequired,
9293
wrappingComponentProps: PropTypes.object,
9394
context: PropTypes.object,
95+
forwardedRef: ref(),
9496
};
9597
WrapperComponent.defaultProps = {
9698
refProp: null,
9799
context: null,
98100
wrappingComponentProps: null,
101+
forwardedRef: undefined,
99102
};
100103

101104
if (options.context && (node.type.contextTypes || options.childContextTypes)) {

packages/enzyme-test-suite/test/ReactWrapper-spec.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,14 @@ describeWithDOM('mount', () => {
107107
describeWithDOM('refs', () => {
108108
it('calls ref', () => {
109109
const spy = sinon.spy();
110+
110111
mount(<div ref={spy} />);
112+
111113
expect(spy).to.have.property('callCount', 1);
114+
115+
const [instance] = spy.firstCall.args;
116+
const element = is('<= 0.13') ? instance.getDOMNode() : instance;
117+
expect(element).to.be.instanceOf(global.HTMLElement);
112118
});
113119

114120
/* global HTMLElement */

0 commit comments

Comments
 (0)