diff --git a/.gitignore b/.gitignore index 4b8d368260..f54d9f3c6a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ logs reports build node_modules +!tests/**/node_modules npm-debug.log sftp-config.json diff --git a/lib/util/version.js b/lib/util/version.js index 97f96ae8ed..4aa472ccaa 100644 --- a/lib/util/version.js +++ b/lib/util/version.js @@ -4,15 +4,35 @@ */ 'use strict'; +const resolve = require('resolve'); const log = require('./log'); let warnedForMissingVersion = false; +function detectReactVersion() { + try { + const reactPath = resolve.sync('react', {basedir: process.cwd()}); + const react = require(reactPath); + return react.version; + } catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + log('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.'); + return '999.999.999'; + } + throw e; + } +} + function getReactVersionFromContext(context) { let confVer = '999.999.999'; // .eslintrc shared settings (http://eslint.org/docs/user-guide/configuring#adding-shared-settings) if (context.settings.react && context.settings.react.version) { - confVer = context.settings.react.version; + let settingsVersion = context.settings.react.version; + if (settingsVersion === 'detect') { + settingsVersion = detectReactVersion(); + } + confVer = settingsVersion; } else if (!warnedForMissingVersion) { log('Warning: React version not specified in eslint-plugin-react settings. ' + 'See https://github.com/yannickcr/eslint-plugin-react#configuration.'); diff --git a/package.json b/package.json index 0337c577e4..fc29be26d1 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "lint": "eslint ./", "pretest": "npm run lint", "test": "npm run unit-test", - "unit-test": "istanbul cover --dir reports/coverage node_modules/mocha/bin/_mocha tests/**/*.js" + "unit-test": "istanbul cover --dir reports/coverage node_modules/mocha/bin/_mocha tests/lib/**/*.js tests/util/**/*.js tests/index.js" }, "files": [ "LICENSE", @@ -29,7 +29,8 @@ "has": "^1.0.3", "jsx-ast-utils": "^2.0.1", "object.fromentries": "^2.0.0", - "prop-types": "^15.6.2" + "prop-types": "^15.6.2", + "resolve": "^1.8.1" }, "devDependencies": { "babel-eslint": "^8.2.5", diff --git a/tests/fixtures/version/detect-version/node_modules/react/index.js b/tests/fixtures/version/detect-version/node_modules/react/index.js new file mode 100644 index 0000000000..022bb03217 --- /dev/null +++ b/tests/fixtures/version/detect-version/node_modules/react/index.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + version: '1.2.3' +}; diff --git a/tests/fixtures/version/detect-version/node_modules/react/package.json b/tests/fixtures/version/detect-version/node_modules/react/package.json new file mode 100644 index 0000000000..56d20a7d44 --- /dev/null +++ b/tests/fixtures/version/detect-version/node_modules/react/package.json @@ -0,0 +1,5 @@ +{ + "name": "react", + "version": "1.2.3", + "main": "index.js" +} diff --git a/tests/util/version.js b/tests/util/version.js new file mode 100644 index 0000000000..5112f8afcd --- /dev/null +++ b/tests/util/version.js @@ -0,0 +1,34 @@ +/* eslint-env mocha */ +'use strict'; + +const path = require('path'); +const assert = require('assert'); +const versionUtil = require('../../lib/util/version'); + +describe('Version', () => { + const base = path.resolve(__dirname, '..', 'fixtures', 'version'); + let cwd; + + beforeEach(() => { + cwd = process.cwd(); + process.chdir(base); + }); + + afterEach(() => { + process.chdir(cwd); + }); + + describe('Detect version', () => { + const context = {settings: {react: {version: 'detect'}}}; + + it('matches detected version', () => { + process.chdir('detect-version'); + assert.equal(versionUtil.testReactVersion(context, '1.2.3'), true); + assert.equal(versionUtil.testReactVersion(context, '1.2.4'), false); + }); + + it('assumes latest version if react is not installed', () => { + assert.equal(versionUtil.testReactVersion(context, '999.999.999'), true); + }); + }); +});