Repository: yannickcr/eslint-plugin-react
Pull request #2336 (2019-06-28 18:44:08)

Handle react version detect errors
### What does this fix
The fix to #2276 (commit https://github.com/golopot/eslint-plugin-react/commit/e2e246afd38dad4ee78d45143fe58e7d878c313c) caused a regression only for scenarios where react version cannot be detected. Once the first warning is logged, a second try always results in the raw error being thrown and failure of the lint process.

```
Warning: React version was set to "detect" in eslint-plugin-react settings, but the "react" package is not installed. Assuming latest React version for linting.
Error: Error while loading rule 'react/jsx-no-bind': Cannot find module 'react' from 'project-path'
Occurred while linting project-path/.eslintrc.js
    at Function.module.exports [as sync] (project-path/node_modules/resolve/lib/sync.js:71:15)
    at detectReactVersion (project-path/node_modules/eslint-plugin-react/lib/util/version.js:19:31)
    at getReactVersionFromContext (project-path/node_modules/eslint-plugin-react/lib/util/version.js:39:25)
    at Object.testReactVersion (project-path/node_modules/eslint-plugin-react/lib/util/version.js:107:35)
    at usedPropTypesInstructions (project-path/node_modules/eslint-plugin-react/lib/util/usedPropTypes.js:271:48)
    at Function.componentRule (project-path/node_modules/eslint-plugin-react/lib/util/Components.js:763:37)
    at createRuleListeners (project-path/node_modules/eslint/lib/linter/linter.js:697:21)
    at Object.keys.forEach.ruleId (project-path/node_modules/eslint/lib/linter/linter.js:865:31)
    at Array.forEach (<anonymous>)
    at runRules (project-path/node_modules/eslint/lib/linter/linter.js:810:34)
npm ERR! Test failed.  See above for more details.
```

### Solution
The `warnedForMissingVersion` flag should only control the warning message and not the handling of the error (which was the previous behavior)

I have included a test that ensures only a single error is present in stack. The issue can be reproduced by going back to the test commit. Here is the output for the case when it fails (i.e. before this fix):

```
 2) Version
       "after each" hook for "warns only once for failure to detect react ":

      AssertionError [ERR_ASSERTION]: [ [ 'Warning: React version was set to "detect" in eslint-plugin-react settings, but the "react" package is not installed. As... deepEqual []
      + expected - actual

      -[
      -  [
      -    "Warning: React version was set to \"detect\" in eslint-plugin-react settings, but the \"react\" package is not installed. Assuming latest React version for linting."
      -  ]
      -]
      +[]
      
      at Context.afterEach (tests/util/version.js:26:12)
```


Patch:
diff --git a/lib/util/version.js b/lib/util/version.js
index 3e8af90c..932866bc 100644
--- a/lib/util/version.js
+++ b/lib/util/version.js
@@ -20,10 +20,12 @@ function detectReactVersion() {
     const react = require(reactPath); // eslint-disable-line import/no-dynamic-require
     return react.version;
   } catch (e) {
-    if (!warnedForMissingVersion && e.code === 'MODULE_NOT_FOUND') {
-      error('Warning: React version was set to "detect" in eslint-plugin-react settings, ' +
+    if (e.code === 'MODULE_NOT_FOUND') {
+      if (!warnedForMissingVersion) {
+        error('Warning: React version was set to "detect" in eslint-plugin-react settings, ' +
         'but the "react" package is not installed. Assuming latest React version for linting.');
-      warnedForMissingVersion = true;
+        warnedForMissingVersion = true;
+      }
       return '999.999.999';
     }
     throw e;


Test patch:
diff --git a/tests/util/version.js b/tests/util/version.js
index 5eacb463..ea8a09b4 100644
--- a/tests/util/version.js
+++ b/tests/util/version.js
@@ -44,6 +44,15 @@ describe('Version', () => {
       ];
     });
 
+    it('warns only once for failure to detect react ', () => {
+      assert.equal(versionUtil.testReactVersion(context, '999.999.999'), true);
+      assert.equal(versionUtil.testReactVersion(context, '999.999.999'), true);
+
+      expectedErrorArgs = [
+        ['Warning: React version was set to "detect" in eslint-plugin-react settings, but the "react" package is not installed. Assuming latest React version for linting.']
+      ];
+    });
+
     it('assumes latest version if flow-bin is not installed', () => {
       assert.equal(versionUtil.testFlowVersion(context, '999.999.999'), true);