diff --git a/docs/api/ShallowWrapper/instance.md b/docs/api/ShallowWrapper/instance.md
index 487a34eac..a67af46e0 100644
--- a/docs/api/ShallowWrapper/instance.md
+++ b/docs/api/ShallowWrapper/instance.md
@@ -30,7 +30,7 @@ class Stateful extends React.Component {
```
#### React 16.x
```jsx
-test('shallow wrapper instance should not be null', () => {
+test('shallow wrapper instance should be null', () => {
const wrapper = shallow();
const instance = wrapper.instance();
diff --git a/package.json b/package.json
index 01c8446d4..5d7c19e48 100644
--- a/package.json
+++ b/package.json
@@ -60,8 +60,6 @@
"author": "Leland Richardson ",
"license": "MIT",
"devDependencies": {
- "acorn": "^6.0.4",
- "acorn-jsx": "^5.0.1",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-eslint": "^7.2.3",
@@ -71,20 +69,19 @@
"babel-register": "^6.26.0",
"chai": "^4.2.0",
"coveralls": "^2.13.3",
- "eslint": "^5.9.0",
+ "eslint": "^5.12.0",
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-markdown": "^1.0.0-rc.0",
- "eslint-plugin-react": "^7.11.1",
- "espree": "^4.1.0",
+ "eslint-plugin-markdown": "^1.0.0",
+ "eslint-plugin-react": "^7.12.2",
"gitbook-cli": "^1.0.1",
"gitbook-plugin-anchors": "^0.7.1",
"gitbook-plugin-codeblock-disable-glossary": "0.0.1",
"gitbook-plugin-collapsible-menu": "^1.0.3",
"gitbook-plugin-edit-link": "^2.0.2",
"gitbook-plugin-github": "^2.0.0",
- "glob-gitignore": "^1.0.9",
+ "glob-gitignore": "^1.0.11",
"in-publish": "^2.0.0",
"istanbul": "^1.0.0-alpha.2",
"istanbul-api": "^1.3.7",
@@ -98,7 +95,7 @@
"lerna": "^2.11.0",
"mocha": "^3.5.3",
"prop-types": "^15.6.2",
- "rimraf": "^2.6.2",
+ "rimraf": "^2.6.3",
"safe-publish-latest": "^1.1.2",
"webpack": "^1.15.0"
},
diff --git a/packages/enzyme-adapter-react-13/package.json b/packages/enzyme-adapter-react-13/package.json
index 94e2938b2..d7dbe0a77 100644
--- a/packages/enzyme-adapter-react-13/package.json
+++ b/packages/enzyme-adapter-react-13/package.json
@@ -52,7 +52,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"rimraf": "^2.6.2",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-react-14/package.json b/packages/enzyme-adapter-react-14/package.json
index 31eb03fcd..7a2c0fe9b 100644
--- a/packages/enzyme-adapter-react-14/package.json
+++ b/packages/enzyme-adapter-react-14/package.json
@@ -55,7 +55,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"rimraf": "^2.6.2",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-react-15.4/package.json b/packages/enzyme-adapter-react-15.4/package.json
index f60312e90..fb7397618 100644
--- a/packages/enzyme-adapter-react-15.4/package.json
+++ b/packages/enzyme-adapter-react-15.4/package.json
@@ -56,7 +56,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"rimraf": "^2.6.2",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-react-15/package.json b/packages/enzyme-adapter-react-15/package.json
index 893dc22d8..71cb14f9c 100644
--- a/packages/enzyme-adapter-react-15/package.json
+++ b/packages/enzyme-adapter-react-15/package.json
@@ -55,7 +55,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"rimraf": "^2.6.2",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-react-16.1/package.json b/packages/enzyme-adapter-react-16.1/package.json
index 0df23ba56..6012166fa 100644
--- a/packages/enzyme-adapter-react-16.1/package.json
+++ b/packages/enzyme-adapter-react-16.1/package.json
@@ -55,7 +55,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"rimraf": "^2.6.2",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-react-16.1/src/ReactSixteenOneAdapter.js b/packages/enzyme-adapter-react-16.1/src/ReactSixteenOneAdapter.js
index d59974ca3..b4ea3a9d5 100644
--- a/packages/enzyme-adapter-react-16.1/src/ReactSixteenOneAdapter.js
+++ b/packages/enzyme-adapter-react-16.1/src/ReactSixteenOneAdapter.js
@@ -29,6 +29,7 @@ import {
ensureKeyOrUndefined,
simulateError,
wrap,
+ getMaskedContext,
} from 'enzyme-adapter-utils';
import { findCurrentFiberUsingSlowPath } from 'react-reconciler/reflection';
@@ -315,7 +316,7 @@ class ReactSixteenOneAdapter extends EnzymeAdapter {
let isDOM = false;
let cachedNode = null;
return {
- render(el, context) {
+ render(el, unmaskedContext) {
cachedNode = el;
/* eslint consistent-return: 0 */
if (typeof el.type === 'string') {
@@ -328,6 +329,7 @@ class ReactSixteenOneAdapter extends EnzymeAdapter {
Component.prototype.isReactComponent
|| Array.isArray(Component.__reactAutoBindPairs) // fallback for createClass components
);
+ const context = getMaskedContext(Component.contextTypes, unmaskedContext);
if (!isStateful && typeof Component === 'function') {
const wrappedEl = Object.assign(
diff --git a/packages/enzyme-adapter-react-16.2/package.json b/packages/enzyme-adapter-react-16.2/package.json
index ab9d703c0..ec8309184 100644
--- a/packages/enzyme-adapter-react-16.2/package.json
+++ b/packages/enzyme-adapter-react-16.2/package.json
@@ -56,7 +56,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"rimraf": "^2.6.2",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-react-16.2/src/ReactSixteenTwoAdapter.js b/packages/enzyme-adapter-react-16.2/src/ReactSixteenTwoAdapter.js
index 4b64a859f..618e36aa4 100644
--- a/packages/enzyme-adapter-react-16.2/src/ReactSixteenTwoAdapter.js
+++ b/packages/enzyme-adapter-react-16.2/src/ReactSixteenTwoAdapter.js
@@ -30,6 +30,7 @@ import {
ensureKeyOrUndefined,
simulateError,
wrap,
+ getMaskedContext,
} from 'enzyme-adapter-utils';
import { findCurrentFiberUsingSlowPath } from 'react-reconciler/reflection';
@@ -317,7 +318,7 @@ class ReactSixteenTwoAdapter extends EnzymeAdapter {
let isDOM = false;
let cachedNode = null;
return {
- render(el, context) {
+ render(el, unmaskedContext) {
cachedNode = el;
/* eslint consistent-return: 0 */
if (typeof el.type === 'string') {
@@ -330,6 +331,7 @@ class ReactSixteenTwoAdapter extends EnzymeAdapter {
Component.prototype.isReactComponent
|| Array.isArray(Component.__reactAutoBindPairs) // fallback for createClass components
);
+ const context = getMaskedContext(Component.contextTypes, unmaskedContext);
if (!isStateful && typeof Component === 'function') {
const wrappedEl = Object.assign(
diff --git a/packages/enzyme-adapter-react-16.3/package.json b/packages/enzyme-adapter-react-16.3/package.json
index 01a8e8180..bcb90c1bb 100644
--- a/packages/enzyme-adapter-react-16.3/package.json
+++ b/packages/enzyme-adapter-react-16.3/package.json
@@ -57,7 +57,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"rimraf": "^2.6.2",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-react-16/package.json b/packages/enzyme-adapter-react-16/package.json
index 6de706e43..b455275a5 100644
--- a/packages/enzyme-adapter-react-16/package.json
+++ b/packages/enzyme-adapter-react-16/package.json
@@ -56,7 +56,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"rimraf": "^2.6.2",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
index 3fe38d6c6..071f707a4 100644
--- a/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
+++ b/packages/enzyme-adapter-react-16/src/ReactSixteenAdapter.js
@@ -41,6 +41,7 @@ import {
ensureKeyOrUndefined,
simulateError,
wrap,
+ getMaskedContext,
} from 'enzyme-adapter-utils';
import findCurrentFiberUsingSlowPath from './findCurrentFiberUsingSlowPath';
import detectFiberTags from './detectFiberTags';
@@ -358,7 +359,7 @@ class ReactSixteenAdapter extends EnzymeAdapter {
let isDOM = false;
let cachedNode = null;
return {
- render(el, context) {
+ render(el, unmaskedContext) {
cachedNode = el;
/* eslint consistent-return: 0 */
if (typeof el.type === 'string') {
@@ -372,6 +373,7 @@ class ReactSixteenAdapter extends EnzymeAdapter {
|| Array.isArray(Component.__reactAutoBindPairs) // fallback for createClass components
);
+ const context = getMaskedContext(Component.contextTypes, unmaskedContext);
if (!isStateful && typeof Component === 'function') {
const wrappedEl = Object.assign(
(...args) => Component(...args), // eslint-disable-line new-cap
diff --git a/packages/enzyme-adapter-react-helper/package.json b/packages/enzyme-adapter-react-helper/package.json
index 052a10e3a..8fd93b863 100644
--- a/packages/enzyme-adapter-react-helper/package.json
+++ b/packages/enzyme-adapter-react-helper/package.json
@@ -46,7 +46,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"react": "0.13.x || 0.14.x || ^15.0.0-0 || ^16.0.0-0 || ^16.3.0-0 || ^16.4.0-0",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-utils/package.json b/packages/enzyme-adapter-utils/package.json
index 06006c870..e4b86bd2a 100644
--- a/packages/enzyme-adapter-utils/package.json
+++ b/packages/enzyme-adapter-utils/package.json
@@ -36,6 +36,7 @@
"dependencies": {
"function.prototype.name": "^1.1.0",
"object.assign": "^4.1.0",
+ "object.fromentries": "^2.0.0",
"prop-types": "^15.6.2",
"semver": "^5.6.0"
},
@@ -50,7 +51,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"rimraf": "^2.6.2",
"safe-publish-latest": "^1.1.2"
diff --git a/packages/enzyme-adapter-utils/src/Utils.js b/packages/enzyme-adapter-utils/src/Utils.js
index d4c37d3e8..35ba6d139 100644
--- a/packages/enzyme-adapter-utils/src/Utils.js
+++ b/packages/enzyme-adapter-utils/src/Utils.js
@@ -1,4 +1,5 @@
import functionName from 'function.prototype.name';
+import fromEntries from 'object.fromentries';
import createMountWrapper from './createMountWrapper';
import createRenderWrapper from './createRenderWrapper';
import wrap from './wrapWithSimpleWrapper';
@@ -282,4 +283,10 @@ export function simulateError(
export function fakeDynamicImport(moduleToImport) {
return Promise.resolve({ default: moduleToImport });
+
+export function getMaskedContext(contextTypes, unmaskedContext) {
+ if (!contextTypes || !unmaskedContext) {
+ return {};
+ }
+ return fromEntries(Object.keys(contextTypes).map(key => [key, unmaskedContext[key]]));
}
diff --git a/packages/enzyme-example-mocha/package.json b/packages/enzyme-example-mocha/package.json
index b3e6e19d4..7abe00e43 100644
--- a/packages/enzyme-example-mocha/package.json
+++ b/packages/enzyme-example-mocha/package.json
@@ -25,7 +25,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"espree": "^4.1.0",
"in-publish": "^2.0.0",
"jsdom": "^11.5.1",
diff --git a/packages/enzyme-test-suite/package.json b/packages/enzyme-test-suite/package.json
index 32842fb2f..ceae11af7 100644
--- a/packages/enzyme-test-suite/package.json
+++ b/packages/enzyme-test-suite/package.json
@@ -52,7 +52,7 @@
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
"eslint-plugin-mocha": "^5.2.0",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"react-is": "^16.7.0"
}
}
diff --git a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
index 69b333a75..3b9359570 100644
--- a/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
+++ b/packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
@@ -4536,6 +4536,30 @@ describe('shallow', () => {
expect(wrapper.context().name).to.equal(context.name);
expect(wrapper.context('name')).to.equal(context.name);
});
+
+ it('filters context to childContextTypes', () => {
+ class Bar extends React.Component {
+ render() {
+ return ;
+ }
+ }
+ Bar.contextTypes = {
+ name: PropTypes.string,
+ };
+ class Foo extends React.Component {
+ render() {
+ return (
+
+
+
+ );
+ }
+ }
+
+ const context = { name: 'foo', hello: 'world' };
+ const wrapper = shallow(, { context });
+ expect(wrapper.find(Bar).dive().context()).to.eql({ name: 'foo' });
+ });
});
describeIf(is('> 0.13'), 'stateless function components', () => {
diff --git a/packages/enzyme-test-suite/test/adapter-utils-spec.jsx b/packages/enzyme-test-suite/test/adapter-utils-spec.jsx
index 162f49f72..a308bd9e6 100644
--- a/packages/enzyme-test-suite/test/adapter-utils-spec.jsx
+++ b/packages/enzyme-test-suite/test/adapter-utils-spec.jsx
@@ -3,6 +3,7 @@ import { expect } from 'chai';
import {
displayNameOfNode,
ensureKeyOrUndefined,
+ getMaskedContext,
} from 'enzyme-adapter-utils';
import './_helpers/setupAdapters';
@@ -82,4 +83,36 @@ describe('enzyme-adapter-utils', () => {
});
});
});
+
+ describe('getMaskedContext', () => {
+ const contextTypes = {
+ a() {},
+ c() {},
+ };
+ const unmaskedContext = {
+ a: 1,
+ b: 2,
+ c: 3,
+ };
+ const falsies = [undefined, null, false, '', NaN, 0];
+
+ it('returns an empty object with falsy `contextTypes`', () => {
+ falsies.forEach((falsy) => {
+ expect(getMaskedContext(falsy, unmaskedContext)).to.eql({});
+ });
+ });
+
+ it('returns an empty object with falsy `unmaskedContext`', () => {
+ falsies.forEach((falsy) => {
+ expect(getMaskedContext(contextTypes, falsy)).to.eql({});
+ });
+ });
+
+ it('filters `unmaskedContext` down to `contextTypes`', () => {
+ expect(getMaskedContext(contextTypes, unmaskedContext)).to.eql({
+ a: unmaskedContext.a,
+ c: unmaskedContext.c,
+ });
+ });
+ });
});
diff --git a/packages/enzyme-test-suite/test/selector-spec.jsx b/packages/enzyme-test-suite/test/selector-spec.jsx
index d9d76bbdb..13d03e3f1 100644
--- a/packages/enzyme-test-suite/test/selector-spec.jsx
+++ b/packages/enzyme-test-suite/test/selector-spec.jsx
@@ -6,7 +6,7 @@ import {
} from 'enzyme';
import './_helpers/setupAdapters';
-import { describeWithDOM } from './_helpers';
+import { describeWithDOM, describeIf } from './_helpers';
const tests = [
{
@@ -283,6 +283,72 @@ describe('selectors', () => {
expect(wrapper.find('span:last-child').text()).to.equal('last');
});
+ describeIf(name === 'mount', ':focus pseudo selector', () => {
+ it('works in mount with directly focused DOM node', () => {
+ const wrapper = renderMethod((
+
+ ));
+ const inputNode = wrapper.find('input');
+
+ expect(inputNode.is(':focus')).to.equal(false);
+
+ const inputDOMNode = wrapper.getDOMNode();
+ inputDOMNode.focus();
+
+ expect(inputNode.is(':focus')).to.equal(true);
+ });
+
+ it('works on component in mount', () => {
+ class ClassComponent extends React.Component {
+ render() {
+ return (
+
+ );
+ }
+ }
+
+ const wrapper = renderMethod((
+
+ ));
+
+ expect(wrapper.find('ClassComponent:focus')).to.have.lengthOf(0);
+
+ const inputDOMNode = wrapper.getDOMNode();
+ inputDOMNode.focus();
+
+ expect(wrapper.find('ClassComponent:focus')).to.have.lengthOf(1);
+ });
+
+ it('works on nested component in mount', () => {
+ class InnerComponent extends React.Component {
+ render() {
+ return (
+
+ );
+ }
+ }
+ class WrapComponent extends React.Component {
+ render() {
+ return ;
+ }
+ }
+ const wrapper = renderMethod((
+
+ ));
+
+ expect(wrapper.find('InnerComponent:focus')).to.have.lengthOf(0);
+ expect(wrapper.find('WrapComponent:focus')).to.have.lengthOf(0);
+ expect(wrapper.find('input:focus')).to.have.lengthOf(0);
+
+ const inputDOMNode = wrapper.getDOMNode();
+ inputDOMNode.focus();
+
+ expect(wrapper.find('InnerComponent:focus')).to.have.lengthOf(1);
+ expect(wrapper.find('WrapComponent:focus')).to.have.lengthOf(1);
+ expect(wrapper.find('input:focus')).to.have.lengthOf(1);
+ });
+ });
+
it('throws for complex selectors in simple selector methods', () => {
const wrapper = renderMethod();
['is', 'filter', 'not', 'every'].forEach((method) => {
diff --git a/packages/enzyme/package.json b/packages/enzyme/package.json
index 75e44631d..90aadce12 100644
--- a/packages/enzyme/package.json
+++ b/packages/enzyme/package.json
@@ -62,7 +62,7 @@
"eslint-config-airbnb": "^17.1.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.2",
- "eslint-plugin-react": "^7.11.1",
+ "eslint-plugin-react": "^7.12.3",
"in-publish": "^2.0.0",
"jsdom": "^6.5.1",
"rimraf": "^2.6.2",
diff --git a/packages/enzyme/src/selectors.js b/packages/enzyme/src/selectors.js
index 57f4a3aff..4b3f42dfe 100644
--- a/packages/enzyme/src/selectors.js
+++ b/packages/enzyme/src/selectors.js
@@ -160,6 +160,14 @@ function matchPseudoSelector(node, token, root) {
const { rendered } = findParentNode(root, node);
return rendered[rendered.length - 1] === node;
}
+ if (name === 'focus') {
+ if (typeof document === 'undefined') {
+ throw new Error('Enzyme::Selector does not support the ":focus" pseudo-element without a global `document`.');
+ }
+ const adapter = getAdapter();
+ /* eslint-env browser */
+ return document.activeElement && adapter.nodeToHostNode(node) === document.activeElement;
+ }
throw new TypeError(`Enzyme::Selector does not support the "${token.name}" pseudo-element or pseudo-class selectors.`);
}