diff --git a/CHANGELOG.md b/CHANGELOG.md index 820ef38767..5c53e403dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,12 +20,14 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel * [`destructuring-assignment`]: fix a false positive for local prop named `context` in SFC ([#2929][] @SyMind) * [`jsx-no-target-blank`]: Allow rel="noreferrer" when `allowReferrer` is true ([#2925][] @edemaine) * [`boolean-prop-naming`]: add check for typescript "boolean" type ([#2930][] @vedadeepta) +* version detection: Add tests that verify versioning works for sibling and child projects ([#2943][] @jcrosetto) ### Changed * [Docs] [`jsx-no-constructed-context-values`][]: fix invalid example syntax ([#2910][] @kud) * [readme] Replace lists of rules with tables in readme ([#2908][] @motato1) * [Docs] added missing curly braces ([#2923][] @Muditxofficial) +[#2943]: https://github.com/yannickcr/eslint-plugin-react/pull/2943 [#2930]: https://github.com/yannickcr/eslint-plugin-react/pull/2930 [#2929]: https://github.com/yannickcr/eslint-plugin-react/pull/2929 [#2925]: https://github.com/yannickcr/eslint-plugin-react/pull/2925 diff --git a/lib/util/version.js b/lib/util/version.js index 951837b899..c34b7c5556 100644 --- a/lib/util/version.js +++ b/lib/util/version.js @@ -6,6 +6,7 @@ 'use strict'; const resolve = require('resolve'); +const path = require('path'); const error = require('./error'); let warnedForMissingVersion = false; @@ -20,13 +21,14 @@ function resetDetectedVersion() { cachedDetectedReactVersion = undefined; } -function detectReactVersion() { +// TODO, semver-major: remove context fallback +function detectReactVersion(context) { if (cachedDetectedReactVersion) { return cachedDetectedReactVersion; } try { - const reactPath = resolve.sync('react', {basedir: process.cwd()}); + const reactPath = resolve.sync('react', {basedir: context ? path.dirname(context.getFilename()) : process.cwd()}); const react = require(reactPath); // eslint-disable-line global-require, import/no-dynamic-require cachedDetectedReactVersion = react.version; return cachedDetectedReactVersion; @@ -50,7 +52,7 @@ function getReactVersionFromContext(context) { if (context.settings && context.settings.react && context.settings.react.version) { let settingsVersion = context.settings.react.version; if (settingsVersion === 'detect') { - settingsVersion = detectReactVersion(); + settingsVersion = detectReactVersion(context); } if (typeof settingsVersion !== 'string') { error('Warning: React version specified in eslint-plugin-react-settings must be a string; ' @@ -66,9 +68,10 @@ function getReactVersionFromContext(context) { return confVer.split('.').map((part) => Number(part)); } -function detectFlowVersion() { +// TODO, semver-major: remove context fallback +function detectFlowVersion(context) { try { - const flowPackageJsonPath = resolve.sync('flow-bin/package.json', {basedir: process.cwd()}); + const flowPackageJsonPath = resolve.sync('flow-bin/package.json', {basedir: context ? path.dirname(context.getFilename()) : process.cwd()}); const flowPackageJson = require(flowPackageJsonPath); // eslint-disable-line global-require, import/no-dynamic-require return flowPackageJson.version; } catch (e) { @@ -87,7 +90,7 @@ function getFlowVersionFromContext(context) { if (context.settings.react && context.settings.react.flowVersion) { let flowVersion = context.settings.react.flowVersion; if (flowVersion === 'detect') { - flowVersion = detectFlowVersion(); + flowVersion = detectFlowVersion(context); } if (typeof flowVersion !== 'string') { error('Warning: Flow version specified in eslint-plugin-react-settings must be a string; ' diff --git a/tests/fixtures/version/detect-version-sibling/node_modules/flow-bin/package.json b/tests/fixtures/version/detect-version-sibling/node_modules/flow-bin/package.json new file mode 100644 index 0000000000..a373038252 --- /dev/null +++ b/tests/fixtures/version/detect-version-sibling/node_modules/flow-bin/package.json @@ -0,0 +1,4 @@ +{ + "name": "flow-bin", + "version": "2.92.0" +} diff --git a/tests/fixtures/version/detect-version-sibling/node_modules/react/index.js b/tests/fixtures/version/detect-version-sibling/node_modules/react/index.js new file mode 100644 index 0000000000..568d6dc9fd --- /dev/null +++ b/tests/fixtures/version/detect-version-sibling/node_modules/react/index.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + version: '2.3.4' +}; diff --git a/tests/fixtures/version/detect-version-sibling/node_modules/react/package.json b/tests/fixtures/version/detect-version-sibling/node_modules/react/package.json new file mode 100644 index 0000000000..54271ba23b --- /dev/null +++ b/tests/fixtures/version/detect-version-sibling/node_modules/react/package.json @@ -0,0 +1,5 @@ +{ + "name": "react", + "version": "2.3.4", + "main": "index.js" +} diff --git a/tests/fixtures/version/detect-version-sibling/test.js b/tests/fixtures/version/detect-version-sibling/test.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/version/detect-version/detect-version-child/node_modules/flow-bin/package.json b/tests/fixtures/version/detect-version/detect-version-child/node_modules/flow-bin/package.json new file mode 100644 index 0000000000..07dbe6adbb --- /dev/null +++ b/tests/fixtures/version/detect-version/detect-version-child/node_modules/flow-bin/package.json @@ -0,0 +1,4 @@ +{ + "name": "flow-bin", + "version": "3.92.0" +} diff --git a/tests/fixtures/version/detect-version/detect-version-child/node_modules/react/index.js b/tests/fixtures/version/detect-version/detect-version-child/node_modules/react/index.js new file mode 100644 index 0000000000..ad81c76a9d --- /dev/null +++ b/tests/fixtures/version/detect-version/detect-version-child/node_modules/react/index.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + version: '3.4.5' +}; diff --git a/tests/fixtures/version/detect-version/detect-version-child/node_modules/react/package.json b/tests/fixtures/version/detect-version/detect-version-child/node_modules/react/package.json new file mode 100644 index 0000000000..3b3aeee383 --- /dev/null +++ b/tests/fixtures/version/detect-version/detect-version-child/node_modules/react/package.json @@ -0,0 +1,5 @@ +{ + "name": "react", + "version": "3.4.5", + "main": "index.js" +} diff --git a/tests/fixtures/version/detect-version/detect-version-child/test.js b/tests/fixtures/version/detect-version/detect-version-child/test.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/fixtures/version/detect-version/test.js b/tests/fixtures/version/detect-version/test.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/util/version.js b/tests/util/version.js index 3e7a0ac561..226ba65f5a 100644 --- a/tests/util/version.js +++ b/tests/util/version.js @@ -7,12 +7,9 @@ const versionUtil = require('../../lib/util/version'); describe('Version', () => { const base = path.resolve(__dirname, '..', 'fixtures', 'version'); - let cwd; let expectedErrorArgs = []; beforeEach(() => { - cwd = process.cwd(); - process.chdir(base); sinon.stub(console, 'error'); expectedErrorArgs = []; versionUtil.resetWarningFlag(); @@ -20,23 +17,44 @@ describe('Version', () => { }); afterEach(() => { - process.chdir(cwd); - const actualArgs = console.error.args; // eslint-disable-line no-console console.error.restore(); // eslint-disable-line no-console assert.deepEqual(actualArgs, expectedErrorArgs); }); describe('Detect version', () => { - const context = {settings: {react: {version: 'detect', flowVersion: 'detect'}}}; + const context = {settings: {react: {version: 'detect', flowVersion: 'detect'}}, getFilename: () => path.resolve(base, 'test.js')}; + + afterEach(() => { + if (context.getFilename.restore) { + context.getFilename.restore(); + } + }); it('matches detected version', () => { - process.chdir('detect-version'); + sinon.stub(context, 'getFilename').callsFake(() => path.resolve(base, 'detect-version', 'test.js')); + assert.equal(versionUtil.testReactVersion(context, '1.2.3'), true); assert.equal(versionUtil.testReactVersion(context, '1.2.4'), false); assert.equal(versionUtil.testFlowVersion(context, '0.92.0'), true); }); + it('matches detected version in sibling project', () => { + sinon.stub(context, 'getFilename').callsFake(() => path.resolve(base, 'detect-version-sibling', 'test.js')); + + assert.equal(versionUtil.testReactVersion(context, '2.3.4'), true); + assert.equal(versionUtil.testReactVersion(context, '2.3.5'), false); + assert.equal(versionUtil.testFlowVersion(context, '2.92.0'), true); + }); + + it('matches detected version in child project', () => { + sinon.stub(context, 'getFilename').callsFake(() => path.resolve(base, 'detect-version', 'detect-version-child', 'test.js')); + + assert.equal(versionUtil.testReactVersion(context, '3.4.5'), true); + assert.equal(versionUtil.testReactVersion(context, '3.4.6'), false); + assert.equal(versionUtil.testFlowVersion(context, '3.92.0'), true); + }); + it('assumes latest version if react is not installed', () => { assert.equal(versionUtil.testReactVersion(context, '999.999.999'), true);