diff --git a/docs/api/ShallowWrapper/dive.md b/docs/api/ShallowWrapper/dive.md
new file mode 100644
index 000000000..c1453823e
--- /dev/null
+++ b/docs/api/ShallowWrapper/dive.md
@@ -0,0 +1,52 @@
+# `.dive([options]) => ShallowWrapper`
+
+Throws unless the wrapper contains only one non-DOM Component child; otherwise, returns a shallow wrapper around it.
+
+NOTE: can only be called on wrapper of a single non-DOM component element node.
+
+
+#### Arguments
+
+1. `options` (`Object` [optional]):
+- `options.context`: (`Object` [optional]): Context to be passed into the component
+
+
+
+#### Returns
+
+`ShallowWrapper`: A new wrapper that wraps the current node after it's been shallow rendered.
+
+
+
+#### Examples
+
+```jsx
+class Bar extends React.Component {
+ render() {
+ return (
+
+ );
+ }
+}
+```
+
+```jsx
+class Foo extends React.Component {
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+```
+
+```jsx
+const wrapper = shallow();
+expect(wrapper.find('.in-bar')).to.have.length(0);
+expect(wrapper.find(Bar)).to.have.length(1);
+expect(wrapper.dive().find('.in-bar')).to.have.length(1);
+```
diff --git a/docs/api/shallow.md b/docs/api/shallow.md
index f9468739d..fb7fa4a3c 100644
--- a/docs/api/shallow.md
+++ b/docs/api/shallow.md
@@ -207,3 +207,6 @@ Returns whether or not all of the nodes in the wrapper match the provided select
#### [`.everyWhere(predicate) => Boolean`](ShallowWrapper/everyWhere.md)
Returns whether or not all of the nodes in the wrapper pass the provided predicate function.
+
+#### [`.dive([options]) => ShallowWrapper`](ShallowWrapper/dive.md)
+Throws unless the wrapper contains only one non-DOM Component child; otherwise, returns a shallow wrapper around it.
diff --git a/src/ShallowWrapper.js b/src/ShallowWrapper.js
index fe0284643..f4c29593e 100644
--- a/src/ShallowWrapper.js
+++ b/src/ShallowWrapper.js
@@ -15,6 +15,7 @@ import {
isReactElementAlike,
displayNameOfNode,
isFunctionalComponent,
+ isCustomComponentElement,
} from './Utils';
import {
debugNodes,
@@ -31,6 +32,7 @@ import {
createShallowRenderer,
renderToStaticMarkup,
batchedUpdates,
+ isDOMComponentElement,
} from './react-compat';
/**
@@ -698,7 +700,7 @@ export default class ShallowWrapper {
/**
* Returns the type of the current node of this wrapper. If it's a composite component, this will
- * be the component constructor. If it's native DOM node, it will be a string.
+ * be the component constructor. If it's a native DOM node, it will be a string.
*
* @returns {String|Function}
*/
@@ -959,4 +961,24 @@ export default class ShallowWrapper {
intercepter(this);
return this;
}
+
+ /**
+ * Primarily useful for HOCs (higher-order components), this method may only be
+ * run on a single, non-DOM node, and will return the node, shallow-rendered.
+ *
+ * @param options object
+ * @returns {ShallowWrapper}
+ */
+ dive(options) {
+ const name = 'dive';
+ return this.single(name, n => {
+ if (isDOMComponentElement(n)) {
+ throw new TypeError(`ShallowWrapper::${name}() can not be called on DOM components`);
+ }
+ if (!isCustomComponentElement(n)) {
+ throw new TypeError(`ShallowWrapper::${name}() can only be called on components`);
+ }
+ return new ShallowWrapper(n, null, options);
+ });
+ }
}