Repository: yannickcr/eslint-plugin-react (js)

Issue:
False positive for react/button-has-type
The following code triggers `react/button-has-type`.

```js
document.createElement('button')
```

The culprit is in this function: https://github.com/yannickcr/eslint-plugin-react/blob/master/lib/rules/button-has-type.js#L15..L20

This should also check for the `pragma` setting.

Pull request:
Account for pragma in button-has-type
Resolves #1847

Patch:
diff --git a/.travis.yml b/.travis.yml
index 67b9cf5a..b4715855 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,6 @@
 sudo: false
 language: node_js
 node_js:
-  - '10'
   - '9'
   - '8'
   - '7'
@@ -16,12 +15,7 @@ script:
   - 'if [ -n "${PRETEST-}" ]; then npm run pretest ; fi'
   - 'if [ -n "${TEST-}" ]; then npm run unit-test ; fi'
 env:
-  global:
-    - TEST=true
-  matrix:
-    - ESLINT=5
-    - ESLINT=4
-    - ESLINT=3
+  - TEST=true
 after_success:
   - 'if [ -n "${TEST-}" ]; then npm run coveralls ; fi'
 matrix:
@@ -29,12 +23,28 @@ matrix:
   include:
     - node_js: 'lts/*'
       env: PRETEST=true
-  exclude:
+    - node_js: '9'
+      env: TEST=true ESLINT=next
+    - node_js: '8'
+      env: TEST=true ESLINT=next
+    - node_js: '7'
+      env: TEST=true ESLINT=next
+    - node_js: '6'
+      env: TEST=true ESLINT=next
+    - node_js: '9'
+      env: TEST=true ESLINT=3
+    - node_js: '8'
+      env: TEST=true ESLINT=3
+    - node_js: '7'
+      env: TEST=true ESLINT=3
+    - node_js: '6'
+      env: TEST=true ESLINT=3
     - node_js: '5'
-      env: ESLINT=5
+      env: TEST=true ESLINT=3
     - node_js: '4'
-      env: ESLINT=5
+      env: TEST=true ESLINT=3
   allow_failures:
     - node_js: '9'
     - node_js: '7'
     - node_js: '5'
+    - env: TEST=true ESLINT=next
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5f91f8e6..78ed2fcb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,32 +3,6 @@ All notable changes to this project will be documented in this file.
 This project adheres to [Semantic Versioning](http://semver.org/).
 This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
 
-## [7.10.0] - 2018-06-24
-### Added
-* Allow eslint ^5 ([#1843][] @papandreou, @ljharb)
-* [`no-unsafe`][] rule ([#1831][], [#1830][] @sergei-startsev)
-* [`no-will-update-set-state`][]: Account for `UNSAFE_` methods ([#1845][], [#1844][] @alexzherdev)
-
-### Fixed
-* [`no-typos`][]: Fix static propTypes handling ([#1827][], [#1677][] @alexzherdev)
-* [`destructuring-assignment`][]: Allow LHS ([#1825][], [#1728][] @alexzherdev)
-* [`no-unused-prop-types`][]: Fix crash when encountering mixed union and intersection flow types ([#1806][] @yannickcr)
-
-### Changed
-* Typo fixes in [`jsx-no-target-blank`][] ([#1805][] @ferhatelmas))
-
-[#1845]: https://github.com/yannickcr/eslint-plugin-react/pull/1845
-[#1844]: https://github.com/yannickcr/eslint-plugin-react/issues/1844
-[#1843]: https://github.com/yannickcr/eslint-plugin-react/pull/1843
-[#1831]: https://github.com/yannickcr/eslint-plugin-react/pull/1831
-[#1830]: https://github.com/yannickcr/eslint-plugin-react/issues/1830
-[#1827]: https://github.com/yannickcr/eslint-plugin-react/pull/1827
-[#1825]: https://github.com/yannickcr/eslint-plugin-react/pull/1825
-[#1806]: https://github.com/yannickcr/eslint-plugin-react/issues/1806
-[#1805]: https://github.com/yannickcr/eslint-plugin-react/pull/1805
-[#1728]: https://github.com/yannickcr/eslint-plugin-react/issues/1728
-[#1677]: https://github.com/yannickcr/eslint-plugin-react/issues/1677
-
 ## [7.9.1] - 2018-06-03
 * Nothing was fixed; this is a republish with some updated deps. ([#1804][] @ljharb)
 
@@ -132,7 +106,6 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
 [#1670]: https://github.com/yannickcr/eslint-plugin-react/pull/1670
 [#1669]: https://github.com/yannickcr/eslint-plugin-react/pull/1669
 [#1666]: https://github.com/yannickcr/eslint-plugin-react/pull/1666
-[#1665]: https://github.com/yannickcr/eslint-plugin-react/pull/1665
 [#1655]: https://github.com/yannickcr/eslint-plugin-react/pull/1655
 [#1610]: https://github.com/yannickcr/eslint-plugin-react/pull/1610
 [#1414]: https://github.com/yannickcr/eslint-plugin-react/pull/1414
@@ -2262,4 +2235,3 @@ If you're still not using React 15 you can keep the old behavior by setting the
 [`jsx-sort-default-props`]: docs/rules/jsx-sort-default-props.md
 [`jsx-max-depth`]: docs/rules/jsx-max-depth.md
 [`jsx-props-no-multi-spaces`]: docs/rules/jsx-props-no-multi-spaces.md
-[`no-unsafe`]: docs/rules/no-unsafe.md
diff --git a/README.md b/README.md
index 5b787b1a..067fe20c 100644
--- a/README.md
+++ b/README.md
@@ -117,7 +117,6 @@ Enable the rules that you would like to use.
 * [react/no-this-in-sfc](docs/rules/no-this-in-sfc.md): Prevent using `this` in stateless functional components
 * [react/no-unescaped-entities](docs/rules/no-unescaped-entities.md): Prevent invalid characters from appearing in markup
 * [react/no-unknown-property](docs/rules/no-unknown-property.md): Prevent usage of unknown DOM property (fixable)
-* [react/no-unsafe](docs/rules/no-unsafe.md): Prevent usage of `UNSAFE_` methods
 * [react/no-unused-prop-types](docs/rules/no-unused-prop-types.md): Prevent definitions of unused prop types
 * [react/no-unused-state](docs/rules/no-unused-state.md): Prevent definitions of unused state properties
 * [react/no-will-update-set-state](docs/rules/no-will-update-set-state.md): Prevent usage of `setState` in `componentWillUpdate`
diff --git a/appveyor.yml b/appveyor.yml
index 74799f46..05ed0fda 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -19,7 +19,6 @@ matrix:
     - nodejs_version: "9"
     - nodejs_version: "7"
     - nodejs_version: "5"
-    - nodejs_version: "4"
 
 platform:
   - x86
diff --git a/docs/rules/no-unsafe.md b/docs/rules/no-unsafe.md
deleted file mode 100644
index 87d30d7c..00000000
--- a/docs/rules/no-unsafe.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Prevent usage of `UNSAFE_` methods (react/no-unsafe)
-
-Certain legacy lifecycle methods are [unsafe for use in async React applications][async_rendering] and cause warnings in [_strict mode_][strict_mode]. These also happen to be the lifecycles that cause the most [confusion within the React community][component_lifecycle_changes].
-
-[async_rendering]: https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html
-[strict_mode]: https://reactjs.org/docs/strict-mode.html#identifying-unsafe-lifecycles
-[component_lifecycle_changes]: https://reactjs.org/blog/2018/03/29/react-v-16-3.html#component-lifecycle-changes
-
-The rule checks the following methods: `UNSAFE_componentWillMount`, `UNSAFE_componentWillReceiveProps`, `UNSAFE_componentWillUpdate`.
-
-## Rule Details
-
-The following patterns are considered warnings:
-
-```jsx
-class Foo extends React.Component {
-  UNSAFE_componentWillMount() {}
-  UNSAFE_componentWillReceiveProps() {}
-  UNSAFE_componentWillUpdate() {}
-}
-```
-
-```jsx
-const Foo = createReactClass({
-  UNSAFE_componentWillMount: function() {},
-  UNSAFE_componentWillReceiveProps: function() {},
-  UNSAFE_componentWillUpdate: function() {}
-});
-```
-
-The following patterns are **not** considered warnings:
-
-```jsx
-class Foo extends Bar {
-  UNSAFE_componentWillMount() {}
-  UNSAFE_componentWillReceiveProps() {}
-  UNSAFE_componentWillUpdate() {}
-}
-```
-
-```jsx
-const Foo = bar({
-  UNSAFE_componentWillMount: function() {},
-  UNSAFE_componentWillReceiveProps: function() {},
-  UNSAFE_componentWillUpdate: function() {}
-});
-```
diff --git a/index.js b/index.js
index 45a96d7d..e311f354 100644
--- a/index.js
+++ b/index.js
@@ -64,7 +64,6 @@ const allRules = {
   'no-typos': require('./lib/rules/no-typos'),
   'no-unescaped-entities': require('./lib/rules/no-unescaped-entities'),
   'no-unknown-property': require('./lib/rules/no-unknown-property'),
-  'no-unsafe': require('./lib/rules/no-unsafe'),
   'no-unused-prop-types': require('./lib/rules/no-unused-prop-types'),
   'no-unused-state': require('./lib/rules/no-unused-state'),
   'no-will-update-set-state': require('./lib/rules/no-will-update-set-state'),
@@ -140,7 +139,6 @@ module.exports = {
         'react/no-string-refs': 2,
         'react/no-unescaped-entities': 2,
         'react/no-unknown-property': 2,
-        'react/no-unsafe': 0,
         'react/prop-types': 2,
         'react/react-in-jsx-scope': 2,
         'react/require-render-return': 2
diff --git a/lib/rules/button-has-type.js b/lib/rules/button-has-type.js
index 64de17bb..724623c3 100644
--- a/lib/rules/button-has-type.js
+++ b/lib/rules/button-has-type.js
@@ -7,15 +7,19 @@
 const getProp = require('jsx-ast-utils/getProp');
 const getLiteralPropValue = require('jsx-ast-utils/getLiteralPropValue');
 const docsUrl = require('../util/docsUrl');
+const pragmaUtil = require('../util/pragma');
 
 // ------------------------------------------------------------------------------
 // Helpers
 // ------------------------------------------------------------------------------
 
-function isCreateElement(node) {
+function isCreateElement(node, context) {
+  const pragma = pragmaUtil.getFromContext(context);
   return node.callee
     && node.callee.type === 'MemberExpression'
     && node.callee.property.name === 'createElement'
+    && node.callee.object
+    && node.callee.object.name === pragma
     && node.arguments.length > 0;
 }
 
@@ -97,7 +101,7 @@ module.exports = {
         checkValue(node, getLiteralPropValue(typeProp));
       },
       CallExpression: function(node) {
-        if (!isCreateElement(node)) {
+        if (!isCreateElement(node, context)) {
           return;
         }
 
diff --git a/lib/rules/forbid-foreign-prop-types.js b/lib/rules/forbid-foreign-prop-types.js
index ba944f94..5e83f891 100644
--- a/lib/rules/forbid-foreign-prop-types.js
+++ b/lib/rules/forbid-foreign-prop-types.js
@@ -81,7 +81,7 @@ module.exports = {
             !isLeftSideOfAssignment(node) &&
             !isAllowedAssignment(node)
           ) || (
-            (node.property.type === 'Literal' || node.property.type === 'JSXText') &&
+            node.property.type === 'Literal' &&
             node.property.value === 'propTypes' &&
             !isLeftSideOfAssignment(node) &&
             !isAllowedAssignment(node)
diff --git a/lib/rules/jsx-curly-brace-presence.js b/lib/rules/jsx-curly-brace-presence.js
index 88f6fa17..4efdb48a 100644
--- a/lib/rules/jsx-curly-brace-presence.js
+++ b/lib/rules/jsx-curly-brace-presence.js
@@ -171,7 +171,7 @@ module.exports = {
       const parentType = JSXExpressionNode.parent.type;
 
       if (
-        (expressionType === 'Literal' || expressionType === 'JSXText') &&
+        expressionType === 'Literal' &&
           typeof expression.value === 'string' &&
           !needToEscapeCharacterForJSX(expression.raw) && (
           parentType === 'JSXElement' ||
@@ -246,7 +246,13 @@ module.exports = {
         }
       },
 
-      'Literal, JSXText': node => {
+      Literal: node => {
+        if (shouldCheckForMissingCurly(node.parent, userConfig)) {
+          reportMissingCurly(node);
+        }
+      },
+
+      JSXText: node => {
         if (shouldCheckForMissingCurly(node.parent, userConfig)) {
           reportMissingCurly(node);
         }
diff --git a/lib/rules/no-unescaped-entities.js b/lib/rules/no-unescaped-entities.js
index db945e85..28de3615 100644
--- a/lib/rules/no-unescaped-entities.js
+++ b/lib/rules/no-unescaped-entities.js
@@ -71,7 +71,13 @@ module.exports = {
     }
 
     return {
-      'Literal, JSXText': function(node) {
+      Literal: function(node) {
+        if (node.parent.type === 'JSXElement') {
+          reportInvalidEntity(node);
+        }
+      },
+
+      JSXText: function(node) {
         if (node.parent.type === 'JSXElement') {
           reportInvalidEntity(node);
         }
diff --git a/lib/rules/no-unsafe.js b/lib/rules/no-unsafe.js
deleted file mode 100644
index 006e5596..00000000
--- a/lib/rules/no-unsafe.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * @fileoverview Prevent usage of UNSAFE_ methods
- * @author Sergei Startsev
- */
-
-'use strict';
-
-const Components = require('../util/Components');
-const astUtil = require('../util/ast');
-const docsUrl = require('../util/docsUrl');
-const versionUtil = require('../util/version');
-
-// ------------------------------------------------------------------------------
-// Rule Definition
-// ------------------------------------------------------------------------------
-
-module.exports = {
-  meta: {
-    docs: {
-      description: 'Prevent usage of UNSAFE_ methods',
-      category: 'Best Practices',
-      recommended: false,
-      url: docsUrl('no-unsafe')
-    },
-    schema: []
-  },
-
-  create: Components.detect((context, components, utils) => {
-    const isApplicable = versionUtil.testReactVersion(context, '16.3.0');
-    if (!isApplicable) {
-      return {};
-    }
-
-    /**
-     * Returns a list of unsafe methods
-     * @returns {Array} A list of unsafe methods
-     */
-    function getUnsafeMethods() {
-      return [
-        'UNSAFE_componentWillMount',
-        'UNSAFE_componentWillReceiveProps',
-        'UNSAFE_componentWillUpdate'
-      ];
-    }
-
-    /**
-     * Checks if a passed method is unsafe
-     * @param {string} method Life cycle method
-     * @returns {boolean} Returns true for unsafe methods, otherwise returns false
-     */
-    function isUnsafe(method) {
-      const unsafeMethods = getUnsafeMethods();
-      return unsafeMethods.indexOf(method) !== -1;
-    }
-
-    /**
-     * Reports the error for an unsafe method
-     * @param {ASTNode} node The AST node being checked
-     * @param {string} method Life cycle method
-     */
-    function checkUnsafe(node, method) {
-      if (!isUnsafe(method)) {
-        return;
-      }
-
-      context.report({
-        node: node,
-        message: `${method} is unsafe for use in async rendering, see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html`
-      });
-    }
-
-    /**
-     * Returns life cycle methods if available
-     * @param {ASTNode} node The AST node being checked.
-     * @returns {Array} The array of methods.
-     */
-    function getLifeCycleMethods(node) {
-      const properties = astUtil.getComponentProperties(node);
-      return properties.map(property => astUtil.getPropertyName(property));
-    }
-
-    /**
-     * Checks life cycle methods
-     * @param {ASTNode} node The AST node being checked.
-     */
-    function checkLifeCycleMethods(node) {
-      if (utils.isES5Component(node) || utils.isES6Component(node)) {
-        const methods = getLifeCycleMethods(node);
-        methods.forEach(method => checkUnsafe(node, method));
-      }
-    }
-
-    return {
-      ClassDeclaration: checkLifeCycleMethods,
-      ClassExpression: checkLifeCycleMethods,
-      ObjectExpression: checkLifeCycleMethods
-    };
-  })
-};
diff --git a/lib/rules/no-unused-state.js b/lib/rules/no-unused-state.js
index 2fbb539d..4d834841 100644
--- a/lib/rules/no-unused-state.js
+++ b/lib/rules/no-unused-state.js
@@ -374,7 +374,13 @@ module.exports = {
         }
       },
 
-      'ExperimentalSpreadProperty, SpreadElement'(node) {
+      ExperimentalSpreadProperty(node) {
+        if (classInfo && isStateReference(node.argument)) {
+          classInfo = null;
+        }
+      },
+
+      SpreadElement(node) {
         if (classInfo && isStateReference(node.argument)) {
           classInfo = null;
         }
diff --git a/lib/rules/no-will-update-set-state.js b/lib/rules/no-will-update-set-state.js
index 22bb6331..51f44ebe 100644
--- a/lib/rules/no-will-update-set-state.js
+++ b/lib/rules/no-will-update-set-state.js
@@ -5,9 +5,5 @@
 'use strict';
 
 const makeNoMethodSetStateRule = require('../util/makeNoMethodSetStateRule');
-const versionUtil = require('../util/version');
 
-module.exports = makeNoMethodSetStateRule(
-  'componentWillUpdate',
-  context => versionUtil.testReactVersion(context, '16.3.0')
-);
+module.exports = makeNoMethodSetStateRule('componentWillUpdate');
diff --git a/lib/util/makeNoMethodSetStateRule.js b/lib/util/makeNoMethodSetStateRule.js
index f885dab7..2b497581 100644
--- a/lib/util/makeNoMethodSetStateRule.js
+++ b/lib/util/makeNoMethodSetStateRule.js
@@ -10,7 +10,7 @@ const docsUrl = require('./docsUrl');
 // Rule Definition
 // ------------------------------------------------------------------------------
 
-function makeNoMethodSetStateRule(methodName, shouldCheckUnsafeCb) {
+function makeNoMethodSetStateRule(methodName) {
   return {
     meta: {
       docs: {
@@ -28,18 +28,6 @@ function makeNoMethodSetStateRule(methodName, shouldCheckUnsafeCb) {
     create: function(context) {
       const mode = context.options[0] || 'allow-in-func';
 
-      function nameMatches(name) {
-        if (name === methodName) {
-          return true;
-        }
-
-        if (typeof shouldCheckUnsafeCb === 'function' && shouldCheckUnsafeCb(context)) {
-          return name === `UNSAFE_${methodName}`;
-        }
-
-        return false;
-      }
-
       // --------------------------------------------------------------------------
       // Public
       // --------------------------------------------------------------------------
@@ -58,20 +46,19 @@ function makeNoMethodSetStateRule(methodName, shouldCheckUnsafeCb) {
           const ancestors = context.getAncestors(callee).reverse();
           let depth = 0;
           for (let i = 0, j = ancestors.length; i < j; i++) {
-            const ancestor = ancestors[i];
-            if (/Function(Expression|Declaration)$/.test(ancestor.type)) {
+            if (/Function(Expression|Declaration)$/.test(ancestors[i].type)) {
               depth++;
             }
             if (
-              (ancestor.type !== 'Property' && ancestor.type !== 'MethodDefinition') ||
-              !nameMatches(ancestor.key.name) ||
+              (ancestors[i].type !== 'Property' && ancestors[i].type !== 'MethodDefinition') ||
+              ancestors[i].key.name !== methodName ||
               (mode !== 'disallow-in-func' && depth > 1)
             ) {
               continue;
             }
             context.report({
               node: callee,
-              message: `Do not use setState in ${ancestor.key.name}`
+              message: `Do not use setState in ${methodName}`
             });
             break;
           }
diff --git a/package.json b/package.json
index 15d1cfe5..3e104277 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-plugin-react",
-  "version": "7.10.0",
+  "version": "7.9.1",
   "author": "Yannick Croissant <yannick.croissant+npm@gmail.com>",
   "description": "React specific linting rules for ESLint",
   "main": "index.js",
@@ -25,19 +25,19 @@
   "bugs": "https://github.com/yannickcr/eslint-plugin-react/issues",
   "dependencies": {
     "doctrine": "^2.1.0",
-    "has": "^1.0.3",
+    "has": "^1.0.2",
     "jsx-ast-utils": "^2.0.1",
-    "prop-types": "^15.6.2"
+    "prop-types": "^15.6.1"
   },
   "devDependencies": {
-    "babel-eslint": "^8.2.5",
+    "babel-eslint": "^8.2.3",
     "coveralls": "^3.0.1",
-    "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0",
+    "eslint": "^4.19.1",
     "istanbul": "^0.4.5",
     "mocha": "^5.2.0"
   },
   "peerDependencies": {
-    "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0"
+    "eslint": "^3.0.0 || ^4.0.0"
   },
   "engines": {
     "node": ">=4"


Test patch:
diff --git a/tests/lib/rules/button-has-type.js b/tests/lib/rules/button-has-type.js
index b4a4a85d..4bd02a16 100644
--- a/tests/lib/rules/button-has-type.js
+++ b/tests/lib/rules/button-has-type.js
@@ -43,6 +43,17 @@ ruleTester.run('button-has-type', rule, {
     {
       code: 'React.createElement("button", {type: "button"})',
       options: [{reset: false}]
+    },
+    {
+      code: 'document.createElement("button")'
+    },
+    {
+      code: 'Foo.createElement("span")',
+      settings: {
+        react: {
+          pragma: 'Foo'
+        }
+      }
     }
   ],
   invalid: [
@@ -83,6 +94,17 @@ ruleTester.run('button-has-type', rule, {
       errors: [{
         message: '"reset" is a forbidden value for button type attribute'
       }]
+    },
+    {
+      code: 'Foo.createElement("button")',
+      errors: [{
+        message: 'Missing an explicit type attribute for button'
+      }],
+      settings: {
+        react: {
+          pragma: 'Foo'
+        }
+      }
     }
   ]
 });
diff --git a/tests/lib/rules/no-unsafe.js b/tests/lib/rules/no-unsafe.js
deleted file mode 100644
index c5e26068..00000000
--- a/tests/lib/rules/no-unsafe.js
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- * @fileoverview Prevent usage of UNSAFE_ methods
- * @author Sergei Startsev
- */
-'use strict';
-
-// ------------------------------------------------------------------------------
-// Requirements
-// ------------------------------------------------------------------------------
-
-const rule = require('../../../lib/rules/no-unsafe');
-const RuleTester = require('eslint').RuleTester;
-
-const parserOptions = {
-  ecmaVersion: 2018,
-  sourceType: 'module',
-  ecmaFeatures: {
-    jsx: true
-  }
-};
-
-function errorMessage(method) {
-  return `${method} is unsafe for use in async rendering, see https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html`;
-}
-
-// ------------------------------------------------------------------------------
-// Tests
-// ------------------------------------------------------------------------------
-
-const ruleTester = new RuleTester({parserOptions});
-ruleTester.run('no-unsafe', rule, {
-  valid: [
-    {
-      code: `
-        class Foo extends React.Component {
-          componentDidUpdate() {}
-          render() {}
-        }
-      `,
-      settings: {react: {version: '16.4.0'}}
-    },
-    {
-      code: `
-        const Foo = createReactClass({
-          componentDidUpdate: function() {},
-          render: function() {}
-        });
-      `,
-      settings: {react: {version: '16.4.0'}}
-    },
-    {
-      code: `
-        class Foo extends Bar {
-          UNSAFE_componentWillMount() {}
-          UNSAFE_componentWillReceiveProps() {}
-          UNSAFE_componentWillUpdate() {}
-        }
-      `,
-      settings: {react: {version: '16.4.0'}}
-    },
-    {
-      code: `
-        const Foo = bar({
-          UNSAFE_componentWillMount: function() {},
-          UNSAFE_componentWillReceiveProps: function() {},
-          UNSAFE_componentWillUpdate: function() {},
-        });
-      `,
-      settings: {react: {version: '16.4.0'}}
-    },
-    {
-      code: `
-        class Foo extends React.Component {
-          UNSAFE_componentWillMount() {}
-          UNSAFE_componentWillReceiveProps() {}
-          UNSAFE_componentWillUpdate() {}
-        }
-      `,
-      settings: {react: {version: '16.2.0'}}
-    },
-    {
-      code: `
-          const Foo = createReactClass({
-            UNSAFE_componentWillMount: function() {},
-            UNSAFE_componentWillReceiveProps: function() {},
-            UNSAFE_componentWillUpdate: function() {},
-          });
-        `,
-      settings: {react: {version: '16.2.0'}}
-    }
-  ],
-
-  invalid: [
-    {
-      code: `
-      class Foo extends React.Component {
-        UNSAFE_componentWillMount() {}
-        UNSAFE_componentWillReceiveProps() {}
-        UNSAFE_componentWillUpdate() {}
-      }
-    `,
-      settings: {react: {version: '16.3.0'}},
-      errors: [
-        {
-          message: errorMessage('UNSAFE_componentWillMount'),
-          line: 2,
-          column: 7,
-          type: 'ClassDeclaration'
-        },
-        {
-          message: errorMessage('UNSAFE_componentWillReceiveProps'),
-          line: 2,
-          column: 7,
-          type: 'ClassDeclaration'
-        },
-        {
-          message: errorMessage('UNSAFE_componentWillUpdate'),
-          line: 2,
-          column: 7,
-          type: 'ClassDeclaration'
-        }
-      ]
-    },
-    {
-      code: `
-        const Foo = createReactClass({
-          UNSAFE_componentWillMount: function() {},
-          UNSAFE_componentWillReceiveProps: function() {},
-          UNSAFE_componentWillUpdate: function() {},
-        });
-      `,
-      settings: {react: {version: '16.3.0'}},
-      errors: [
-        {
-          message: errorMessage('UNSAFE_componentWillMount'),
-          line: 2,
-          column: 38,
-          type: 'ObjectExpression'
-        },
-        {
-          message: errorMessage('UNSAFE_componentWillReceiveProps'),
-          line: 2,
-          column: 38,
-          type: 'ObjectExpression'
-        },
-        {
-          message: errorMessage('UNSAFE_componentWillUpdate'),
-          line: 2,
-          column: 38,
-          type: 'ObjectExpression'
-        }
-      ]
-    }
-  ]
-});
diff --git a/tests/lib/rules/no-will-update-set-state.js b/tests/lib/rules/no-will-update-set-state.js
index c2bec1d6..25afca0b 100644
--- a/tests/lib/rules/no-will-update-set-state.js
+++ b/tests/lib/rules/no-will-update-set-state.js
@@ -77,17 +77,6 @@ ruleTester.run('no-will-update-set-state', rule, {
       });
     `,
     parser: 'babel-eslint'
-  }, {
-    code: `
-      class Hello extends React.Component {
-        UNSAFE_componentWillUpdate() {
-          this.setState({
-            data: data
-          });
-        }
-      }
-    `,
-    settings: {react: {version: '16.2.0'}}
   }],
 
   invalid: [{
@@ -236,33 +225,5 @@ ruleTester.run('no-will-update-set-state', rule, {
     errors: [{
       message: 'Do not use setState in componentWillUpdate'
     }]
-  }, {
-    code: `
-      class Hello extends React.Component {
-        UNSAFE_componentWillUpdate() {
-          this.setState({
-            data: data
-          });
-        }
-      }
-    `,
-    settings: {react: {version: '16.3.0'}},
-    errors: [{
-      message: 'Do not use setState in UNSAFE_componentWillUpdate'
-    }]
-  }, {
-    code: `
-      var Hello = createReactClass({
-        UNSAFE_componentWillUpdate: function() {
-          this.setState({
-            data: data
-          });
-        }
-      });
-    `,
-    settings: {react: {version: '16.3.0'}},
-    errors: [{
-      message: 'Do not use setState in UNSAFE_componentWillUpdate'
-    }]
   }]
 });