Skip to content

Commit

Permalink
Merge pull request #1863 from dferber90/master
Browse files Browse the repository at this point in the history
[New] `mount`/`shallow`: Add renderProp

 - [enzyme-adapter-react-*] [New] add `.wrap` method
  • Loading branch information
ljharb committed Nov 5, 2018
2 parents 3bd7a40 + d725261 commit 6cdd27c
Show file tree
Hide file tree
Showing 20 changed files with 457 additions and 2 deletions.
85 changes: 85 additions & 0 deletions docs/api/ReactWrapper/renderProp.md
@@ -0,0 +1,85 @@
# `.renderProp(propName, ...args) => ReactWrapper`

Calls the current wrapper's property with name `propName` and the `args` provided.
Returns the result in a new wrapper.

NOTE: can only be called on wrapper of a single non-DOM component element node.

#### Arguments

1. `propName` (`String`):
1. `...args` (`Array<Any>`):

This essentially calls `wrapper.prop(propName)(...args)`.

#### Returns

`ReactWrapper`: A new wrapper that wraps the node returned from the render prop.

#### Examples

##### Test Setup

```jsx
class Mouse extends React.Component {
constructor() {
super();
this.state = { x: 0, y: 0 };
}

render() {
const { render } = this.props;
return (
<div
style={{ height: '100%' }}
onMouseMove={(event) => {
this.setState({
x: event.clientX,
y: event.clientY,
});
}}
>
{render(this.state)}
</div>
);
}
}

Mouse.propTypes = {
render: PropTypes.func.isRequired,
};
```

```jsx
const App = () => (
<div style={{ height: '100%' }}>
<Mouse
render={(x = 0, y = 0) => (
<h1>
The mouse position is ({x}, {y})
</h1>
)}
/>
</div>
);
```

##### Testing with no arguments

```jsx
const wrapper = mount(<App />)
.find(Mouse)
.renderProp('render');

expect(wrapper.equals(<h1>The mouse position is 0, 0</h1>)).to.equal(true);
```

##### Testing with multiple arguments

```jsx
const wrapper = mount(<App />)
.find(Mouse)
.renderProp('render', [10, 20]);

expect(wrapper.equals(<h1>The mouse position is 10, 20</h1>)).to.equal(true);
```
85 changes: 85 additions & 0 deletions docs/api/ShallowWrapper/renderProp.md
@@ -0,0 +1,85 @@
# `.renderProp(propName, ...args) => ShallowWrapper`

Calls the current wrapper's property with name `propName` and the `args` provided.
Returns the result in a new wrapper.

NOTE: can only be called on wrapper of a single non-DOM component element node.

#### Arguments

1. `propName` (`String`):
1. `...args` (`Array<Any>`):

This essentially calls `wrapper.prop(propName)(...args)`.

#### Returns

`ShallowWrapper`: A new wrapper that wraps the node returned from the render prop.

#### Examples

##### Test Setup

```jsx
class Mouse extends React.Component {
constructor() {
super();
this.state = { x: 0, y: 0 };
}

render() {
const { render } = this.props;
return (
<div
style={{ height: '100%' }}
onMouseMove={(event) => {
this.setState({
x: event.clientX,
y: event.clientY,
});
}}
>
{render(this.state)}
</div>
);
}
}

Mouse.propTypes = {
render: PropTypes.func.isRequired,
};
```

```jsx
const App = () => (
<div style={{ height: '100%' }}>
<Mouse
render={(x = 0, y = 0) => (
<h1>
The mouse position is ({x}, {y})
</h1>
)}
/>
</div>
);
```

##### Testing with no arguments

```jsx
const wrapper = shallow(<App />)
.find(Mouse)
.renderProp('render');

expect(wrapper.equals(<h1>The mouse position is 0, 0</h1>)).to.equal(true);
```

##### Testing with multiple arguments

```jsx
const wrapper = shallow(<App />)
.find(Mouse)
.renderProp('render', [10, 20]);

expect(wrapper.equals(<h1>The mouse position is 10, 20</h1>)).to.equal(true);
```
3 changes: 3 additions & 0 deletions docs/api/mount.md
Expand Up @@ -120,6 +120,9 @@ Get a wrapper with the first ancestor of the current node to match the provided
#### [`.render() => CheerioWrapper`](ReactWrapper/render.md)
Returns a CheerioWrapper of the current node's subtree.

#### [`.renderProp(key) => ReactWrapper`](ReactWrapper/renderProp.md)
Returns a wrapper of the node rendered by the provided render prop.

#### [`.text() => String`](ReactWrapper/text.md)
Returns a string representation of the text nodes in the current render tree.

Expand Down
3 changes: 3 additions & 0 deletions docs/api/shallow.md
Expand Up @@ -130,6 +130,9 @@ Shallow renders the current node and returns a shallow wrapper around it.
#### [`.render() => CheerioWrapper`](ShallowWrapper/render.md)
Returns a CheerioWrapper of the current node's subtree.

#### [`.renderProp(key) => ShallowWrapper`](ShallowWrapper/renderProp.md)
Returns a wrapper of the node rendered by the provided render prop.

#### [`.unmount() => ShallowWrapper`](ShallowWrapper/unmount.md)
A method that un-mounts the component.

Expand Down
5 changes: 5 additions & 0 deletions packages/enzyme-adapter-react-13/src/ReactThirteenAdapter.js
Expand Up @@ -14,6 +14,7 @@ import {
createMountWrapper,
propsWithKeysAndRef,
ensureKeyOrUndefined,
wrap,
} from 'enzyme-adapter-utils';
import mapNativeEventNames from './ReactThirteenMapNativeEventNames';
import elementToTree from './ReactThirteenElementToTree';
Expand Down Expand Up @@ -242,6 +243,10 @@ class ReactThirteenAdapter extends EnzymeAdapter {
}
}

wrap(element) {
return wrap(element);
}

// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed
// in order to implement the `Wrapper.mount()` and `Wrapper.shallow()` methods, but should
// be pretty straightforward for people to implement.
Expand Down
5 changes: 5 additions & 0 deletions packages/enzyme-adapter-react-14/src/ReactFourteenAdapter.js
Expand Up @@ -18,6 +18,7 @@ import {
createMountWrapper,
propsWithKeysAndRef,
ensureKeyOrUndefined,
wrap,
} from 'enzyme-adapter-utils';

function typeToNodeType(type) {
Expand Down Expand Up @@ -214,6 +215,10 @@ class ReactFourteenAdapter extends EnzymeAdapter {
}
}

wrap(element) {
return wrap(element);
}

// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed
// in order to implement the `Wrapper.mount()` and `Wrapper.shallow()` methods, but should
// be pretty straightforward for people to implement.
Expand Down
Expand Up @@ -18,6 +18,7 @@ import {
createMountWrapper,
propsWithKeysAndRef,
ensureKeyOrUndefined,
wrap,
} from 'enzyme-adapter-utils';
import ifReact from 'enzyme-adapter-react-helper/build/ifReact';

Expand Down Expand Up @@ -249,6 +250,10 @@ class ReactFifteenFourAdapter extends EnzymeAdapter {
}
}

wrap(element) {
return wrap(element);
}

// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed
// in order to implement the `Wrapper.mount()` and `Wrapper.shallow()` methods, but should
// be pretty straightforward for people to implement.
Expand Down
5 changes: 5 additions & 0 deletions packages/enzyme-adapter-react-15/src/ReactFifteenAdapter.js
Expand Up @@ -20,6 +20,7 @@ import {
createMountWrapper,
propsWithKeysAndRef,
ensureKeyOrUndefined,
wrap,
} from 'enzyme-adapter-utils';

function compositeTypeToNodeType(type) {
Expand Down Expand Up @@ -249,6 +250,10 @@ class ReactFifteenAdapter extends EnzymeAdapter {
}
}

wrap(element) {
return wrap(element);
}

// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed
// in order to implement the `Wrapper.mount()` and `Wrapper.shallow()` methods, but should
// be pretty straightforward for people to implement.
Expand Down
Expand Up @@ -28,6 +28,7 @@ import {
propsWithKeysAndRef,
ensureKeyOrUndefined,
simulateError,
wrap,
} from 'enzyme-adapter-utils';
import { findCurrentFiberUsingSlowPath } from 'react-reconciler/reflection';

Expand Down Expand Up @@ -440,6 +441,10 @@ class ReactSixteenOneAdapter extends EnzymeAdapter {
}
}

wrap(element) {
return wrap(element);
}

// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed
// in order to implement the `Wrapper.mount()` and `Wrapper.shallow()` methods, but should
// be pretty straightforward for people to implement.
Expand Down
Expand Up @@ -29,6 +29,7 @@ import {
propsWithKeysAndRef,
ensureKeyOrUndefined,
simulateError,
wrap,
} from 'enzyme-adapter-utils';
import { findCurrentFiberUsingSlowPath } from 'react-reconciler/reflection';

Expand Down Expand Up @@ -442,6 +443,10 @@ class ReactSixteenTwoAdapter extends EnzymeAdapter {
}
}

wrap(element) {
return wrap(element);
}

// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed
// in order to implement the `Wrapper.mount()` and `Wrapper.shallow()` methods, but should
// be pretty straightforward for people to implement.
Expand Down
Expand Up @@ -36,6 +36,7 @@ import {
propsWithKeysAndRef,
ensureKeyOrUndefined,
simulateError,
wrap,
} from 'enzyme-adapter-utils';
import { findCurrentFiberUsingSlowPath } from 'react-reconciler/reflection';

Expand Down Expand Up @@ -422,6 +423,10 @@ class ReactSixteenThreeAdapter extends EnzymeAdapter {
}
}

wrap(element) {
return wrap(element);
}

// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed
// in order to implement the `Wrapper.mount()` and `Wrapper.shallow()` methods, but should
// be pretty straightforward for people to implement.
Expand Down
5 changes: 5 additions & 0 deletions packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
Expand Up @@ -38,6 +38,7 @@ import {
propsWithKeysAndRef,
ensureKeyOrUndefined,
simulateError,
wrap,
} from 'enzyme-adapter-utils';
import findCurrentFiberUsingSlowPath from './findCurrentFiberUsingSlowPath';
import detectFiberTags from './detectFiberTags';
Expand Down Expand Up @@ -468,6 +469,10 @@ class ReactSixteenAdapter extends EnzymeAdapter {
}
}

wrap(element) {
return wrap(element);
}

// converts an RSTNode to the corresponding JSX Pragma Element. This will be needed
// in order to implement the `Wrapper.mount()` and `Wrapper.shallow()` methods, but should
// be pretty straightforward for people to implement.
Expand Down
3 changes: 2 additions & 1 deletion packages/enzyme-adapter-utils/package.json
Expand Up @@ -36,7 +36,8 @@
"dependencies": {
"function.prototype.name": "^1.1.0",
"object.assign": "^4.1.0",
"prop-types": "^15.6.2"
"prop-types": "^15.6.2",
"semver": "^5.6.0"
},
"peerDependencies": {
"react": "0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0"
Expand Down
3 changes: 2 additions & 1 deletion packages/enzyme-adapter-utils/src/Utils.js
@@ -1,8 +1,9 @@
import functionName from 'function.prototype.name';
import createMountWrapper from './createMountWrapper';
import createRenderWrapper from './createRenderWrapper';
import wrap from './wrapWithSimpleWrapper';

export { createMountWrapper, createRenderWrapper };
export { createMountWrapper, createRenderWrapper, wrap };

export function mapNativeEventNames(event, {
animation = false, // should be true for React 15+
Expand Down
29 changes: 29 additions & 0 deletions packages/enzyme-adapter-utils/src/wrapWithSimpleWrapper.jsx
@@ -0,0 +1,29 @@
import React from 'react';
import { intersects } from 'semver';
import PropTypes from 'prop-types';

const propTypes = {
children: PropTypes.element.isRequired,
};

const Wrapper = (intersects('>= 0.14', React.version)
// eslint-disable-next-line prefer-arrow-callback
? () => Object.assign(function SimpleSFCWrapper({ children }) {
return children;
}, { propTypes })
: () => {
class SimpleClassWrapper extends React.Component {
render() {
const { children } = this.props;
return children;
}
}
SimpleClassWrapper.propTypes = propTypes;
return SimpleClassWrapper;
}
)();

export default function wrap(element) {
console.log(React.version, Wrapper);
return <Wrapper>{element}</Wrapper>;
}

0 comments on commit 6cdd27c

Please sign in to comment.