diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e467dc470..34a53d9805 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel ### Fixed * [`propTypes`]: add `VoidFunctionComponent` to react generic list ([#3092][] @vedadeepta) +* [`jsx-fragments`], [`jsx-no-useless-fragment`]: avoid a crash on fragment syntax in `typescript-eslint` parser (@ljharb) +* [`jsx-props-no-multi-spaces`]: avoid a crash on long member chains in tag names in `typescript-eslint` parser (@ljharb) +* [`no-unused-prop-types`], `usedPropTypes`: avoid crash with typescript-eslint parser (@ljharb) [#3092]: https://github.com/yannickcr/eslint-plugin-react/pull/3092 [#2166]: https://github.com/yannickcr/eslint-plugin-react/pull/2166 diff --git a/lib/rules/jsx-fragments.js b/lib/rules/jsx-fragments.js index 090d735fd8..7354eecc39 100644 --- a/lib/rules/jsx-fragments.js +++ b/lib/rules/jsx-fragments.js @@ -66,6 +66,11 @@ module.exports = { function getFixerToLong(jsxFragment) { const sourceCode = context.getSourceCode(); + if (!jsxFragment.closingFragment || !jsxFragment.openingFragment) { + // the old TS parser crashes here + // TODO: FIXME: can we fake these two descriptors? + return null; + } return function fix(fixer) { let source = sourceCode.getText(); source = replaceNode(source, jsxFragment.closingFragment, closeFragLong); diff --git a/lib/rules/jsx-no-useless-fragment.js b/lib/rules/jsx-no-useless-fragment.js index 5f48a0c591..ac197e9da9 100644 --- a/lib/rules/jsx-no-useless-fragment.js +++ b/lib/rules/jsx-no-useless-fragment.js @@ -186,6 +186,11 @@ module.exports = { return false; } + // old TS parser can't handle this one + if (node.type === 'JSXFragment' && (!node.openingFragment || !node.closingFragment)) { + return false; + } + return true; } diff --git a/lib/rules/jsx-props-no-multi-spaces.js b/lib/rules/jsx-props-no-multi-spaces.js index f0e5c01f0e..b0d34d59dd 100644 --- a/lib/rules/jsx-props-no-multi-spaces.js +++ b/lib/rules/jsx-props-no-multi-spaces.js @@ -44,7 +44,9 @@ module.exports = { case 'JSXMemberExpression': return `${getPropName(propNode.object)}.${propNode.property.name}`; default: - return propNode.name.name; + return propNode.name + ? propNode.name.name + : `${context.getSourceCode().getText(propNode.object)}.${propNode.property.name}`; // needed for typescript-eslint parser } } diff --git a/lib/util/usedPropTypes.js b/lib/util/usedPropTypes.js index de2249d7c2..7b11745105 100644 --- a/lib/util/usedPropTypes.js +++ b/lib/util/usedPropTypes.js @@ -145,7 +145,7 @@ function isInLifeCycleMethod(node, checkAsyncSafeLifeCycles) { * @return {boolean} */ function isSetStateUpdater(node) { - const unwrappedParentCalleeNode = node.parent.type === 'CallExpression' + const unwrappedParentCalleeNode = node.parent && node.parent.type === 'CallExpression' && ast.unwrapTSAsExpression(node.parent.callee); return unwrappedParentCalleeNode diff --git a/tests/helpers/parsers.js b/tests/helpers/parsers.js index 8376cfba67..9f0afb9b79 100644 --- a/tests/helpers/parsers.js +++ b/tests/helpers/parsers.js @@ -3,26 +3,67 @@ const path = require('path'); const semver = require('semver'); const version = require('eslint/package.json').version; +const flatMap = require('array.prototype.flatmap'); const NODE_MODULES = '../../node_modules'; -module.exports = { +const parsers = { BABEL_ESLINT: path.join(__dirname, NODE_MODULES, 'babel-eslint'), TYPESCRIPT_ESLINT: path.join(__dirname, NODE_MODULES, 'typescript-eslint-parser'), '@TYPESCRIPT_ESLINT': path.join(__dirname, NODE_MODULES, '@typescript-eslint/parser'), - TS: function TS(tests) { - if (!Array.isArray(tests) || arguments.length > 1) { - throw new SyntaxError('parsers.TS() takes a single array argument'); - } - if (semver.satisfies(version, '>= 5')) { - return tests; - } - return []; - }, - ES2020: function ES2020(tests) { - if (semver.satisfies(version, '>= 6')) { - return tests; - } - return []; + all: function all(tests) { + const t = flatMap(tests, (test) => { + if (typeof test === 'string') { + test = { code: test }; + } + if ('parser' in test) { + delete test.features; + return test; + } + const features = new Set([].concat(test.features || [])); + delete test.features; + const es = test.parserOptions && test.parserOptions.ecmaVersion; + + function addComment(testObject, parser) { + const extraComment = `\n// features: [${Array.from(features).join(',')}], parser: ${parser}`; + return Object.assign( + {}, + testObject, + { code: testObject.code + extraComment }, + testObject.output && { output: testObject.output + extraComment } + ); + } + + const skipBase = (features.has('class fields') && semver.satisfies(version, '< 8')) + || (es >= 2020 && semver.satisfies(version, '< 6')) + || features.has('no-default') + || features.has('bind operator') + || features.has('do expressions') + || features.has('decorators') + || features.has('flow') + || features.has('ts') + || features.has('types') + || (features.has('fragment') && semver.satisfies(version, '< 5')); + + const skipBabel = features.has('no-babel'); + const skipTS = semver.satisfies(version, '< 5') + || features.has('flow') + || features.has('no-ts') + || features.has('jsx namespace') + || features.has('bind operator') + || features.has('do expressions'); + const tsOld = !skipTS && !features.has('no-ts-old'); + const tsNew = !skipTS && !features.has('no-ts-new'); + + return [].concat( + skipBase ? [] : addComment(test, 'default'), + skipBabel ? [] : addComment(Object.assign({}, test, { parser: parsers.BABEL_ESLINT }), 'babel-eslint'), + tsOld ? addComment(Object.assign({}, test, { parser: parsers.TYPESCRIPT_ESLINT }), 'typescript-eslint') : [], + tsNew ? addComment(Object.assign({}, test, { parser: parsers['@TYPESCRIPT_ESLINT'] }), '@typescript/eslint') : [] + ); + }); + return t; }, }; + +module.exports = parsers; diff --git a/tests/lib/rules/boolean-prop-naming.js b/tests/lib/rules/boolean-prop-naming.js index 7adf938761..b9a797a657 100644 --- a/tests/lib/rules/boolean-prop-naming.js +++ b/tests/lib/rules/boolean-prop-naming.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('boolean-prop-naming', rule, { - valid: [].concat( + valid: parsers.all([ { // Should support both `is` and `has` prefixes by default code: ` @@ -46,9 +46,7 @@ ruleTester.run('boolean-prop-naming', rule, { render: function() { return
; } }); `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { // createReactClass components with React.PropTypes @@ -58,9 +56,7 @@ ruleTester.run('boolean-prop-naming', rule, { render: function() { return
; } }); `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { // React.createClass components with PropTypes @@ -70,9 +66,7 @@ ruleTester.run('boolean-prop-naming', rule, { render: function() { return
; } }); `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], settings: { react: { createClass: 'createClass', @@ -87,9 +81,7 @@ ruleTester.run('boolean-prop-naming', rule, { render: function() { return
; } }); `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], settings: { react: { createClass: 'createClass', @@ -104,9 +96,7 @@ ruleTester.run('boolean-prop-naming', rule, { } Hello.propTypes = {isSomething: PropTypes.bool} `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { // ES6 components as React.Component with non-boolean PropTypes @@ -116,9 +106,7 @@ ruleTester.run('boolean-prop-naming', rule, { } Hello.propTypes = wrap({ a: PropTypes.bool }) `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { code: ` @@ -127,9 +115,7 @@ ruleTester.run('boolean-prop-naming', rule, { } Hello.propTypes = {something: PropTypes.any} `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { // ES6 components as Component with boolean PropTypes @@ -139,9 +125,7 @@ ruleTester.run('boolean-prop-naming', rule, { } Hello.propTypes = {isSomething: PropTypes.bool} `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { // ES6 components with static class properties and PropTypes @@ -151,10 +135,8 @@ ruleTester.run('boolean-prop-naming', rule, { render () { return
; } } `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['class fields'], }, { // ES6 components with static class properties and Object.spread syntax in PropTypes @@ -165,10 +147,8 @@ ruleTester.run('boolean-prop-naming', rule, { render () { return
; } } `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['class fields'], }, { // ES6 components as Component with boolean PropTypes and Object.spread syntax in PropTypes @@ -179,9 +159,7 @@ ruleTester.run('boolean-prop-naming', rule, { } Hello.propTypes = {isSomething: PropTypes.bool, ...spreadProps} `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { // ES6 components with static class properties and React.PropTypes @@ -191,10 +169,8 @@ ruleTester.run('boolean-prop-naming', rule, { render () { return
; } } `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['class fields'], }, { // ES6 components with static class properties an non-booleans @@ -204,10 +180,8 @@ ruleTester.run('boolean-prop-naming', rule, { render () { return
; } } `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['class fields'], }, { // ES6 components and Flowtype booleans @@ -217,10 +191,8 @@ ruleTester.run('boolean-prop-naming', rule, { render () { return
; } } `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['class fields', 'flow'], }, { // ES6 components and Flowtype non-booleans @@ -230,10 +202,8 @@ ruleTester.run('boolean-prop-naming', rule, { render () { return
; } } `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['flow'], }, { // Stateless components @@ -241,10 +211,7 @@ ruleTester.run('boolean-prop-naming', rule, { var Hello = ({isSomething}) => { return
} Hello.propTypes = {isSomething: PropTypes.bool}; `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { // Functional components and Flowtype booleans @@ -254,10 +221,8 @@ ruleTester.run('boolean-prop-naming', rule, { }; function Hello(props: Props): React.Element { return
} `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['flow'], }, { // Custom `propTypeNames` option @@ -276,7 +241,7 @@ ruleTester.run('boolean-prop-naming', rule, { rule: '^is[A-Z]([A-Za-z0-9]?)+', }, ], - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { // Custom PropTypes that are specified as variables @@ -295,7 +260,7 @@ ruleTester.run('boolean-prop-naming', rule, { rule: '^is[A-Z]([A-Za-z0-9]?)+', }, ], - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { // Ensure rule doesn't crash on destructured objects [Issue #1369] @@ -303,10 +268,7 @@ ruleTester.run('boolean-prop-naming', rule, { var x = {a: 1} var y = {...x} `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { // Ensure rule doesn't crash on on components reference old-style Flow props @@ -316,10 +278,8 @@ ruleTester.run('boolean-prop-naming', rule, { render () { return
} } `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['flow'], }, { // No propWrapperFunctions setting @@ -330,9 +290,7 @@ ruleTester.run('boolean-prop-naming', rule, { Card.propTypes = merge({}, Card.propTypes, { showScore: PropTypes.bool });`, - options: [ - { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }], }, { // Ensure the rule does not throw when a prop isRequired when ES5. @@ -359,7 +317,7 @@ ruleTester.run('boolean-prop-naming', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { // Ensure the rule does not throw when a prop isRequired when ES6 without static properties. @@ -386,9 +344,7 @@ ruleTester.run('boolean-prop-naming', rule, { render: function() { return
; } }); `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], }, { // inline Flow type @@ -403,10 +359,8 @@ ruleTester.run('boolean-prop-naming', rule, { ); } `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['flow'], }, { code: ` @@ -451,687 +405,650 @@ ruleTester.run('boolean-prop-naming', rule, { validateNested: true, }, ], - }, parsers.TS([ - { - code: ` - type TestFNType = { - isEnabled: boolean - } - const HelloNew = (props: TestFNType) => { return
}; - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers['@TYPESCRIPT_ESLINT'], - errors: [], - }, - ]) - ), - - invalid: [].concat({ - // createReactClass components with PropTypes - code: ` - var Hello = createReactClass({ - propTypes: {something: PropTypes.bool}, - render: function() { return
; } - }); - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // createReactClass components with React.PropTypes - code: ` - var Hello = createReactClass({ - propTypes: {something: React.PropTypes.bool}, - render: function() { return
; } - }); - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // React.createClass components with PropTypes - code: ` - var Hello = React.createClass({ - propTypes: {something: PropTypes.bool}, - render: function() { return
; } - }); - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - settings: { - react: { - createClass: 'createClass', - }, - }, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // ES6 components as React.Component with boolean PropTypes - code: ` - class Hello extends React.Component { - render () { return
; } - } - Hello.propTypes = {something: PropTypes.bool} - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // ES6 components as Component with non-boolean PropTypes - code: ` - class Hello extends Component { - render () { return
; } - } - Hello.propTypes = {something: PropTypes.bool} - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // ES6 components as React.Component with non-boolean PropTypes - code: ` - class Hello extends React.Component { - static propTypes = {something: PropTypes.bool}; - render () { return
; } - } - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // ES6 components as React.Component with non-boolean PropTypes and Object.spread syntax - code: ` - const spreadProps = { aSpreadProp: PropTypes.string }; - class Hello extends Component { - render () { return
; } - } - Hello.propTypes = {something: PropTypes.bool, ...spreadProps} - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // ES6 components as React.Component with static class property, non-boolean PropTypes, and Object.spread syntax - code: ` - const spreadProps = { aSpreadProp: PropTypes.string }; - class Hello extends React.Component { - static propTypes = {something: PropTypes.bool, ...spreadProps}; - render () { return
; } - } - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // ES6 components as React.Component with non-boolean PropTypes - code: ` - class Hello extends React.Component { - props: {something: boolean}; - render () { return
; } - } - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - var Hello = ({something}) => { return
} - Hello.propTypes = {something: PropTypes.bool}; - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - type Props = { - something: boolean; - }; - function Hello(props: Props): React.Element { return
} - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // ES6 components and Flowtype non-booleans - code: ` - class Hello extends React.Component { - static propTypes = {something: PropTypes.mutuallyExclusiveTrueProps}; - render () { return
; } - } - `, - options: [ - { - propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'], - rule: '^is[A-Z]([A-Za-z0-9]?)+', - }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - class Hello extends React.Component { - static propTypes = { - something: PropTypes.mutuallyExclusiveTrueProps, - somethingElse: PropTypes.bool - }; - render () { return
; } - } - `, - options: [ - { - propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'], - rule: '^is[A-Z]([A-Za-z0-9]?)+', - }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - { - messageId: 'patternMismatch', - data: { propName: 'somethingElse', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - class Hello extends React.Component { - static propTypes = { - something: mutuallyExclusiveTrueProps, - somethingElse: bool - }; - render () { return
; } - } - `, - options: [ - { - propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'], - rule: '^is[A-Z]([A-Za-z0-9]?)+', - }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - { - messageId: 'patternMismatch', - data: { propName: 'somethingElse', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - function Card(props) { - return
{props.showScore ? 'yeh' : 'no'}
; - } - Card.propTypes = merge({}, Card.propTypes, { - showScore: PropTypes.bool - });`, - settings: { - propWrapperFunctions: ['merge'], - }, - options: [ - { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - function Card(props) { - return
{props.showScore ? 'yeh' : 'no'}
; - } - Card.propTypes = Object.assign({}, Card.propTypes, { - showScore: PropTypes.bool - });`, - settings: { - propWrapperFunctions: ['Object.assign'], }, - options: [ - { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - function Card(props) { - return
{props.showScore ? 'yeh' : 'no'}
; - } - Card.propTypes = _.assign({}, Card.propTypes, { - showScore: PropTypes.bool - });`, - settings: { - propWrapperFunctions: ['_.assign'], + { + code: ` + type TestFNType = { + isEnabled: boolean + } + const HelloNew = (props: TestFNType) => { return
}; + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['ts'], + errors: [], }, - options: [ - { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - function Card(props) { - return
{props.showScore ? 'yeh' : 'no'}
; - } - Card.propTypes = forbidExtraProps({ - showScore: PropTypes.bool - });`, - settings: { - propWrapperFunctions: ['forbidExtraProps'], + ]), + + invalid: parsers.all([ + { + // createReactClass components with PropTypes + code: ` + var Hello = createReactClass({ + propTypes: {something: PropTypes.bool}, + render: function() { return
; } + }); + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], }, - options: [ - { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - class Card extends React.Component { - render() { - return
{props.showScore ? 'yeh' : 'no'}
; - } - } - Card.propTypes = forbidExtraProps({ - showScore: PropTypes.bool - });`, - settings: { - propWrapperFunctions: ['forbidExtraProps'], + { + // createReactClass components with React.PropTypes + code: ` + var Hello = createReactClass({ + propTypes: {something: React.PropTypes.bool}, + render: function() { return
; } + }); + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], }, - options: [ - { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + { + // React.createClass components with PropTypes + code: ` + var Hello = React.createClass({ + propTypes: {something: PropTypes.bool}, + render: function() { return
; } + }); + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + settings: { + react: { + createClass: 'createClass', + }, }, - ], - }, - { - code: ` - class Card extends React.Component { - static propTypes = forbidExtraProps({ - showScore: PropTypes.bool - }); - render() { - return
{props.showScore ? 'yeh' : 'no'}
; - } - }`, - parser: parsers.BABEL_ESLINT, - settings: { - propWrapperFunctions: ['forbidExtraProps'], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], }, - options: [ - { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // If a custom message is provided, use it. - code: ` - class Hello extends React.Component { - render () { return
; } - } - Hello.propTypes = {something: PropTypes.bool} - `, - options: [ - { - rule: '^is[A-Z]([A-Za-z0-9]?)+', - message: 'Boolean prop names must begin with either \'is\' or \'has\'', - }, - ], - errors: [ - { - message: 'Boolean prop names must begin with either \'is\' or \'has\'', - }, - ], - }, - { - // Custom messages use eslint string templating. - code: ` - class Hello extends React.Component { - render () { return
; } - } - Hello.propTypes = {something: PropTypes.bool} - `, - options: [ - { - rule: '^is[A-Z]([A-Za-z0-9]?)+', - message: 'It is better if your prop ({{ propName }}) matches this pattern: ({{ pattern }})', - }, - ], - errors: [ - { - message: 'It is better if your prop (something) matches this pattern: (^is[A-Z]([A-Za-z0-9]?)+)', - }, - ], - }, - { - // Works when a prop isRequired in ES5. - code: ` - var Hello = createReactClass({ - propTypes: {something: PropTypes.bool.isRequired}, - render: function() { return
; } - }); - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // Works when a prop isRequired in ES6 with static properties. - code: ` - class Hello extends React.Component { - static propTypes = { - something: PropTypes.bool.isRequired - }; - - render() { - return ( -
- ); - } - } - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // Works when a prop isRequired in ES6 without static properties. - code: ` - class Hello extends React.Component { - render() { - return ( -
- ); - } - } - - Hello.propTypes = { - something: PropTypes.bool.isRequired - } - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - // inline Flow type - code: ` - function SomeComponent({ - something, - }: { - something: boolean, - }) { - return ( - {something} - ); - } - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers.BABEL_ESLINT, - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - class Hello extends React.Component { - render() { - return ( -
- ); - } - } - - Hello.propTypes = { - isSomething: PropTypes.bool.isRequired, - nested: PropTypes.shape({ - failingItIs: PropTypes.bool - }) - }; - `, - options: [ - { - rule: '^is[A-Z]([A-Za-z0-9]?)+', - validateNested: true, - }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'failingItIs', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - class Hello extends React.Component { - render() { - return ( -
- ); - } - } - - Hello.propTypes = { - isSomething: PropTypes.bool.isRequired, - nested: PropTypes.shape({ - nested: PropTypes.shape({ - failingItIs: PropTypes.bool - }) - }) - }; - `, - options: [ - { - rule: '^is[A-Z]([A-Za-z0-9]?)+', - validateNested: true, - }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'failingItIs', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, - { - code: ` - import { bool } from 'prop-types'; - var Hello = createReactClass({ - propTypes: {something: bool}, - render: function() { return
; } - }); - `, - options: [ - { - rule: '^is[A-Z]([A-Za-z0-9]?)+', - validateNested: true, - }, - ], - errors: [ - { - messageId: 'patternMismatch', - data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, - }, - ], - }, parsers.TS([ { + // ES6 components as React.Component with boolean PropTypes code: ` - type TestConstType = { - enabled: boolean + class Hello extends React.Component { + render () { return
; } } - const HelloNew = (props: TestConstType) => { return
}; - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, - ], - parser: parsers['@TYPESCRIPT_ESLINT'], + Hello.propTypes = {something: PropTypes.bool} + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], errors: [ { - message: 'Prop name (enabled) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)', + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, }, ], }, { + // ES6 components as Component with non-boolean PropTypes code: ` - type TestFNType = { - enabled: boolean + class Hello extends Component { + render () { return
; } } - const HelloNew = (props: TestFNType) => { return
}; - `, - options: [ - { rule: '^is[A-Z]([A-Za-z0-9]?)+' }, + Hello.propTypes = {something: PropTypes.bool} + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, ], - parser: parsers['@TYPESCRIPT_ESLINT'], + }, + { + // ES6 components as React.Component with non-boolean PropTypes + code: ` + class Hello extends React.Component { + static propTypes = {something: PropTypes.bool}; + render () { return
; } + } + `, + features: ['class fields'], + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + // ES6 components as React.Component with non-boolean PropTypes and Object.spread syntax + code: ` + const spreadProps = { aSpreadProp: PropTypes.string }; + class Hello extends Component { + render () { return
; } + } + Hello.propTypes = {something: PropTypes.bool, ...spreadProps} + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + // ES6 components as React.Component with static class property, non-boolean PropTypes, and Object.spread syntax + code: ` + const spreadProps = { aSpreadProp: PropTypes.string }; + class Hello extends React.Component { + static propTypes = {something: PropTypes.bool, ...spreadProps}; + render () { return
; } + } + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['class fields'], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + // ES6 components as React.Component with non-boolean PropTypes + code: ` + class Hello extends React.Component { + props: {something: boolean}; + render () { return
; } + } + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['flow'], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + var Hello = ({something}) => { return
} + Hello.propTypes = {something: PropTypes.bool}; + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + type Props = { + something: boolean; + }; + function Hello(props: Props): React.Element { return
} + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['types', 'no-ts-old'], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + // ES6 components and Flowtype non-booleans + code: ` + class Hello extends React.Component { + static propTypes = {something: PropTypes.mutuallyExclusiveTrueProps}; + render () { return
; } + } + `, + options: [ + { + propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'], + rule: '^is[A-Z]([A-Za-z0-9]?)+', + }, + ], + features: ['flow'], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + class Hello extends React.Component { + static propTypes = { + something: PropTypes.mutuallyExclusiveTrueProps, + somethingElse: PropTypes.bool + }; + render () { return
; } + } + `, + options: [ + { + propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'], + rule: '^is[A-Z]([A-Za-z0-9]?)+', + }, + ], + features: ['class fields'], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + { + messageId: 'patternMismatch', + data: { propName: 'somethingElse', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + class Hello extends React.Component { + static propTypes = { + something: mutuallyExclusiveTrueProps, + somethingElse: bool + }; + render () { return
; } + } + `, + options: [ + { + propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'], + rule: '^is[A-Z]([A-Za-z0-9]?)+', + }, + ], + features: ['class fields'], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + { + messageId: 'patternMismatch', + data: { propName: 'somethingElse', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + function Card(props) { + return
{props.showScore ? 'yeh' : 'no'}
; + } + Card.propTypes = merge({}, Card.propTypes, { + showScore: PropTypes.bool + });`, + settings: { + propWrapperFunctions: ['merge'], + }, + options: [ + { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + ], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + function Card(props) { + return
{props.showScore ? 'yeh' : 'no'}
; + } + Card.propTypes = Object.assign({}, Card.propTypes, { + showScore: PropTypes.bool + });`, + settings: { + propWrapperFunctions: ['Object.assign'], + }, + options: [ + { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + ], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + function Card(props) { + return
{props.showScore ? 'yeh' : 'no'}
; + } + Card.propTypes = _.assign({}, Card.propTypes, { + showScore: PropTypes.bool + });`, + settings: { + propWrapperFunctions: ['_.assign'], + }, + options: [ + { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + ], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + function Card(props) { + return
{props.showScore ? 'yeh' : 'no'}
; + } + Card.propTypes = forbidExtraProps({ + showScore: PropTypes.bool + });`, + settings: { + propWrapperFunctions: ['forbidExtraProps'], + }, + options: [ + { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + ], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + class Card extends React.Component { + render() { + return
{props.showScore ? 'yeh' : 'no'}
; + } + } + Card.propTypes = forbidExtraProps({ + showScore: PropTypes.bool + });`, + settings: { + propWrapperFunctions: ['forbidExtraProps'], + }, + options: [ + { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + ], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + class Card extends React.Component { + static propTypes = forbidExtraProps({ + showScore: PropTypes.bool + }); + render() { + return
{props.showScore ? 'yeh' : 'no'}
; + } + }`, + features: ['class fields'], + settings: { + propWrapperFunctions: ['forbidExtraProps'], + }, + options: [ + { rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + ], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'showScore', pattern: '^(is|has)[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + // If a custom message is provided, use it. + code: ` + class Hello extends React.Component { + render () { return
; } + } + Hello.propTypes = {something: PropTypes.bool} + `, + options: [ + { + rule: '^is[A-Z]([A-Za-z0-9]?)+', + message: 'Boolean prop names must begin with either \'is\' or \'has\'', + }, + ], + errors: [ + { + message: 'Boolean prop names must begin with either \'is\' or \'has\'', + }, + ], + }, + { + // Custom messages use eslint string templating. + code: ` + class Hello extends React.Component { + render () { return
; } + } + Hello.propTypes = {something: PropTypes.bool} + `, + options: [ + { + rule: '^is[A-Z]([A-Za-z0-9]?)+', + message: 'It is better if your prop ({{ propName }}) matches this pattern: ({{ pattern }})', + }, + ], + errors: [ + { + message: 'It is better if your prop (something) matches this pattern: (^is[A-Z]([A-Za-z0-9]?)+)', + }, + ], + }, + { + // Works when a prop isRequired in ES5. + code: ` + var Hello = createReactClass({ + propTypes: {something: PropTypes.bool.isRequired}, + render: function() { return
; } + }); + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + // Works when a prop isRequired in ES6 with static properties. + code: ` + class Hello extends React.Component { + static propTypes = { + something: PropTypes.bool.isRequired + }; + + render() { + return ( +
+ ); + } + } + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['class fields'], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + // Works when a prop isRequired in ES6 without static properties. + code: ` + class Hello extends React.Component { + render() { + return ( +
+ ); + } + } + + Hello.propTypes = { + something: PropTypes.bool.isRequired + } + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + // inline Flow type + code: ` + function SomeComponent({ + something, + }: { + something: boolean, + }) { + return ( + {something} + ); + } + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['flow'], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + class Hello extends React.Component { + render() { + return ( +
+ ); + } + } + + Hello.propTypes = { + isSomething: PropTypes.bool.isRequired, + nested: PropTypes.shape({ + failingItIs: PropTypes.bool + }) + }; + `, + options: [ + { + rule: '^is[A-Z]([A-Za-z0-9]?)+', + validateNested: true, + }, + ], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'failingItIs', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + class Hello extends React.Component { + render() { + return ( +
+ ); + } + } + + Hello.propTypes = { + isSomething: PropTypes.bool.isRequired, + nested: PropTypes.shape({ + nested: PropTypes.shape({ + failingItIs: PropTypes.bool + }) + }) + }; + `, + options: [ + { + rule: '^is[A-Z]([A-Za-z0-9]?)+', + validateNested: true, + }, + ], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'failingItIs', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + import { bool } from 'prop-types'; + var Hello = createReactClass({ + propTypes: {something: bool}, + render: function() { return
; } + }); + `, + options: [ + { + rule: '^is[A-Z]([A-Za-z0-9]?)+', + validateNested: true, + }, + ], + errors: [ + { + messageId: 'patternMismatch', + data: { propName: 'something', pattern: '^is[A-Z]([A-Za-z0-9]?)+' }, + }, + ], + }, + { + code: ` + type TestConstType = { + enabled: boolean + } + const HelloNew = (props: TestConstType) => { return
}; + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['ts', 'no-ts-old'], + errors: [ + { + message: 'Prop name (enabled) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)', + }, + ], + }, + { + code: ` + type TestFNType = { + enabled: boolean + } + const HelloNew = (props: TestFNType) => { return
}; + `, + options: [{ rule: '^is[A-Z]([A-Za-z0-9]?)+' }], + features: ['ts', 'no-ts-old'], errors: [ { message: 'Prop name (enabled) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)', }, ], }, - ])), + ]), }); diff --git a/tests/lib/rules/button-has-type.js b/tests/lib/rules/button-has-type.js index 7dbfc16c4f..8c7ab73955 100644 --- a/tests/lib/rules/button-has-type.js +++ b/tests/lib/rules/button-has-type.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/button-has-type'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('button-has-type', rule, { - valid: [ + valid: parsers.all([ { code: '' }, { code: '' }, { code: '
`, - parser: parsers.BABEL_ESLINT, options: [{ children: 'always' }], }, { @@ -398,6 +393,7 @@ ruleTester.run('jsx-curly-brace-presence', rule, { return /*; }; `, + features: ['no-ts-old'], // the old TS parser hangs forever on this one }, { code: ` @@ -406,6 +402,7 @@ ruleTester.run('jsx-curly-brace-presence', rule, { }; `, options: [{ props: 'never', children: 'never' }], + features: ['no-ts-old'], // the old TS parser hangs forever on this one }, { code: ` @@ -416,6 +413,7 @@ ruleTester.run('jsx-curly-brace-presence', rule, { }; `, options: [{ props: 'never', children: 'never' }], + features: ['no-ts-old'], // the old TS parser hangs forever on this one }, { code: `{/* comment */}`, @@ -441,9 +439,9 @@ ruleTester.run('jsx-curly-brace-presence', rule, { `, }, ] : []) - ), + )), - invalid: [ + invalid: parsers.all([ { code: '', output: '', @@ -476,7 +474,7 @@ ruleTester.run('jsx-curly-brace-presence', rule, { { code: '<>{`foo`}', output: '<>foo', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ children: 'never' }], errors: [{ messageId: 'unnecessaryCurly' }], }, @@ -513,7 +511,6 @@ ruleTester.run('jsx-curly-brace-presence', rule, { % `, - parser: parsers.BABEL_ESLINT, options: [{ children: 'never' }], errors: [{ messageId: 'unnecessaryCurly' }], }, @@ -536,7 +533,6 @@ ruleTester.run('jsx-curly-brace-presence', rule, { baz `, - parser: parsers.BABEL_ESLINT, options: [{ children: 'never' }], errors: [ { messageId: 'unnecessaryCurly' }, @@ -565,7 +561,7 @@ ruleTester.run('jsx-curly-brace-presence', rule, { {'some-complicated-exp'} `, - parser: parsers.BABEL_ESLINT, + features: ['no-default', 'no-ts-new'], // TODO: FIXME: remove no-default and no-ts-new and fix options: [{ children: 'never' }], errors: [{ messageId: 'unnecessaryCurly' }, { messageId: 'unnecessaryCurly' }], }, @@ -592,7 +588,6 @@ ruleTester.run('jsx-curly-brace-presence', rule, { output: `foo`, options: [{ props: 'always' }], errors: [{ messageId: 'missingCurly' }], - parser: parsers.BABEL_ESLINT, }, { code: 'foo bar ', @@ -860,5 +855,5 @@ ruleTester.run('jsx-curly-brace-presence', rule, { errors: [{ messageId: 'unnecessaryCurly' }], options: ['never'], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-curly-newline.js b/tests/lib/rules/jsx-curly-newline.js index 385df60510..894e21834f 100644 --- a/tests/lib/rules/jsx-curly-newline.js +++ b/tests/lib/rules/jsx-curly-newline.js @@ -11,6 +11,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-curly-newline'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -36,7 +38,7 @@ const MULTILINE_REQUIRE = [{ singleline: 'consistent', multiline: 'require' }]; const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-curly-newline', rule, { - valid: [ + valid: parsers.all([ // consistent option (default) { code: '
{foo}
', @@ -137,9 +139,9 @@ ruleTester.run('jsx-curly-newline', rule, { `, options: NEVER, }, - ], + ]), - invalid: [ + invalid: parsers.all([ // consistent option (default) { code: ` @@ -310,5 +312,5 @@ ruleTester.run('jsx-curly-newline', rule, { options: NEVER, errors: [RIGHT_UNEXPECTED_ERROR], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-curly-spacing.js b/tests/lib/rules/jsx-curly-spacing.js index bd33a843a5..3eec41b99a 100644 --- a/tests/lib/rules/jsx-curly-spacing.js +++ b/tests/lib/rules/jsx-curly-spacing.js @@ -29,7 +29,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-curly-spacing', rule, { - valid: [ + valid: parsers.all([ { code: ';', }, @@ -488,7 +488,6 @@ ruleTester.run('jsx-curly-spacing', rule, { } />; `, options: [{ attributes: { when: 'never' } }], - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -764,7 +763,6 @@ ruleTester.run('jsx-curly-spacing', rule, { } />; `, options: ['always'], - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -830,15 +828,14 @@ ruleTester.run('jsx-curly-spacing', rule, { }, { code: '<>{bar} {baz};', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '
{ /* dummy callback to fix android bug with component measuring */ }} />', - parser: parsers.BABEL_ESLINT, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: '{bar};', output: '{bar};', @@ -943,7 +940,7 @@ ruleTester.run('jsx-curly-spacing', rule, { { code: '<>{ bar };', output: '<>{bar};', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ children: true }], errors: [ { @@ -3445,5 +3442,5 @@ ruleTester.run('jsx-curly-spacing', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-equals-spacing.js b/tests/lib/rules/jsx-equals-spacing.js index 3f8c597121..78c97898c6 100644 --- a/tests/lib/rules/jsx-equals-spacing.js +++ b/tests/lib/rules/jsx-equals-spacing.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-equals-spacing'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-equals-spacing', rule, { - valid: [ + valid: parsers.all([ { code: '', }, @@ -82,9 +84,9 @@ ruleTester.run('jsx-equals-spacing', rule, { code: '', options: ['always'], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: '', output: '', @@ -155,5 +157,5 @@ ruleTester.run('jsx-equals-spacing', rule, { { messageId: 'needSpaceAfter' }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-filename-extension.js b/tests/lib/rules/jsx-filename-extension.js index 11c2e2403a..2fa3d676f1 100644 --- a/tests/lib/rules/jsx-filename-extension.js +++ b/tests/lib/rules/jsx-filename-extension.js @@ -36,7 +36,7 @@ const withoutJSX = 'module.exports = {}'; const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-filename-extension', rule, { - valid: [ + valid: parsers.all([ { filename: '', code: withJSXElement, @@ -67,22 +67,22 @@ ruleTester.run('jsx-filename-extension', rule, { { filename: '', code: withJSXFragment, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { filename: 'MyComponent.jsx', code: withJSXFragment, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { filename: 'MyComponent.js', options: [{ extensions: ['.js', '.jsx'] }], code: withJSXFragment, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { filename: 'MyComponent.js', code: withJSXElement, @@ -129,7 +129,7 @@ ruleTester.run('jsx-filename-extension', rule, { { filename: 'MyComponent.js', code: withJSXFragment, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], errors: [ { messageId: 'noJSXWithExtension', @@ -140,7 +140,7 @@ ruleTester.run('jsx-filename-extension', rule, { { filename: 'MyComponent.jsx', code: withJSXFragment, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ extensions: ['.js'] }], errors: [ { @@ -149,5 +149,5 @@ ruleTester.run('jsx-filename-extension', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-first-prop-new-line.js b/tests/lib/rules/jsx-first-prop-new-line.js index 3fa9ffd4ce..8fea1441fc 100644 --- a/tests/lib/rules/jsx-first-prop-new-line.js +++ b/tests/lib/rules/jsx-first-prop-new-line.js @@ -29,288 +29,185 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-first-prop-new-line', rule, { - - valid: [ + valid: parsers.all([ { code: '', options: ['never'], - parser: parsers.BABEL_ESLINT, }, { code: '', options: ['never'], - parser: parsers.BABEL_ESLINT, }, { code: '', options: ['never'], - parser: parsers.BABEL_ESLINT, }, { code: '', options: ['never'], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), + code: ` + + `, options: ['never'], - parser: parsers.BABEL_ESLINT, }, { code: '', options: ['multiline'], - parser: parsers.BABEL_ESLINT, }, { code: '', options: ['multiline'], - parser: parsers.BABEL_ESLINT, }, { code: '', options: ['multiline'], - parser: parsers.BABEL_ESLINT, }, { code: '', options: ['multiline'], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), + code: ` + + `, options: ['multiline'], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), + code: ` + + `, options: ['multiline'], - parser: parsers.BABEL_ESLINT, - }, - { - code: [ - '', - ].join('\n'), - options: ['multiline-multiprop'], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), + code: ` + + `, options: ['multiline-multiprop'], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), + code: ` + + `, options: ['multiline-multiprop'], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), + code: ` + + `, options: ['multiline-multiprop'], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), + code: ` + + `, options: ['multiline-multiprop'], - parser: parsers.TYPESCRIPT_ESLINT, }, { code: '', options: ['always'], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), + code: ` + + `, options: ['always'], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), + code: ` + + `, options: ['always'], - parser: parsers.BABEL_ESLINT, }, - ], + ]), - invalid: [ - { - code: '', - output: [ - '', - ].join('\n'), - options: ['always'], - errors: [{ messageId: 'propOnNewLine' }], - parser: parsers.BABEL_ESLINT, - }, - { - code: '', - output: [ - '', - ].join('\n'), - options: ['always'], - errors: [{ messageId: 'propOnNewLine' }], - parser: parsers.TYPESCRIPT_ESLINT, - }, - { - code: [ - '', - ].join('\n'), - output: [ - '', - ].join('\n'), + invalid: parsers.all([ + { + code: ` + + `, + output: ` + + `, options: ['always'], errors: [{ messageId: 'propOnNewLine' }], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), - output: [ - '', - ].join('\n'), + code: ` + + `, + output: ` + + `, options: ['always'], errors: [{ messageId: 'propOnNewLine' }], - parser: parsers.TYPESCRIPT_ESLINT, }, { - code: [ - '', - ].join('\n'), - output: [ - '', - ].join('\n'), + code: ` + + `, + output: ` + + `, options: ['never'], errors: [{ messageId: 'propOnSameLine' }], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), - output: [ - '', - ].join('\n'), - options: ['never'], - errors: [{ messageId: 'propOnSameLine' }], - parser: parsers.TYPESCRIPT_ESLINT, - }, - { - code: [ - '', - ].join('\n'), - output: [ - '', - ].join('\n'), - options: ['multiline'], - errors: [{ messageId: 'propOnNewLine' }], - parser: parsers.BABEL_ESLINT, - }, - { - code: [ - '', - ].join('\n'), - output: [ - '', - ].join('\n'), + code: ` + + `, + output: ` + + `, options: ['multiline'], errors: [{ messageId: 'propOnNewLine' }], - parser: parsers.TYPESCRIPT_ESLINT, - }, - { - code: [ - '', - ].join('\n'), - output: [ - '', - ].join('\n'), - options: ['multiline-multiprop'], - errors: [{ messageId: 'propOnNewLine' }], - parser: parsers.BABEL_ESLINT, }, { - code: [ - '', - ].join('\n'), - output: [ - '', - ].join('\n'), + code: ` + + `, + output: ` + + `, options: ['multiline-multiprop'], errors: [{ messageId: 'propOnNewLine' }], - parser: parsers.TYPESCRIPT_ESLINT, }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-fragments.js b/tests/lib/rules/jsx-fragments.js index cc4db71a2a..1ee6fb3fa2 100644 --- a/tests/lib/rules/jsx-fragments.js +++ b/tests/lib/rules/jsx-fragments.js @@ -44,10 +44,10 @@ const settingsOld = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-fragments', rule, { - valid: [ + valid: parsers.all([ { code: '<>', - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], settings, }, { @@ -102,12 +102,12 @@ ruleTester.run('jsx-fragments', rule, { options: ['syntax'], settings, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: '<>', - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], settings: settingsOld, errors: [ { messageId: 'fragmentsNotSupported' }, @@ -130,7 +130,20 @@ ruleTester.run('jsx-fragments', rule, { { code: '<>', output: '', - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], + options: ['element'], + settings, + errors: [ + { + messageId: 'preferPragma', + data: { react: 'Act', fragment: 'Frag' }, + }, + ], + }, + { + code: '<>', + output: '<>', // should get '', but the old TS parser lacks opening/closing Fragment info + features: ['fragment', 'no-babel', 'ts', 'no-ts-new'], options: ['element'], settings, errors: [ @@ -272,5 +285,5 @@ ruleTester.run('jsx-fragments', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-handler-names.js b/tests/lib/rules/jsx-handler-names.js index 670707eccc..3aba45beba 100644 --- a/tests/lib/rules/jsx-handler-names.js +++ b/tests/lib/rules/jsx-handler-names.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-handler-names', rule, { - valid: [ + valid: parsers.all([ { code: '', }, @@ -118,29 +118,29 @@ ruleTester.run('jsx-handler-names', rule, { }, { code: '', - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: '', - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: '', - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: ' props::handleChange()} />', - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], options: [{ checkInlineFunction: true }], }, { code: ' ::props.onChange()} />', - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], options: [{ checkInlineFunction: true }], }, { code: ' props.foo::handleChange()} />', - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], options: [{ checkInlineFunction: true }], }, { @@ -181,9 +181,9 @@ ruleTester.run('jsx-handler-names', rule, { code: '', options: [{ eventHandlerPropPrefix: false }], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: '', errors: [ @@ -351,7 +351,7 @@ ruleTester.run('jsx-handler-names', rule, { }, { code: '', - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], errors: [ { messageId: 'badHandlerName', @@ -361,7 +361,7 @@ ruleTester.run('jsx-handler-names', rule, { }, { code: '', - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], errors: [ { messageId: 'badHandlerName', @@ -369,5 +369,5 @@ ruleTester.run('jsx-handler-names', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-indent-props.js b/tests/lib/rules/jsx-indent-props.js index cf638a29d7..bfa5f20d9d 100644 --- a/tests/lib/rules/jsx-indent-props.js +++ b/tests/lib/rules/jsx-indent-props.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-indent-props'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-indent-props', rule, { - valid: [ + valid: parsers.all([ { code: ` @@ -38,7 +38,7 @@ ruleTester.run('jsx-indent', rule, { code: ` <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -51,7 +51,7 @@ ruleTester.run('jsx-indent', rule, { <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -67,7 +67,7 @@ ruleTester.run('jsx-indent', rule, { <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -76,7 +76,7 @@ ruleTester.run('jsx-indent', rule, { `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -121,7 +121,7 @@ ruleTester.run('jsx-indent', rule, { ; } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -142,7 +142,7 @@ ruleTester.run('jsx-indent', rule, { ); } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -167,7 +167,7 @@ ruleTester.run('jsx-indent', rule, { ); } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -192,7 +192,7 @@ ruleTester.run('jsx-indent', rule, { ) ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -237,7 +237,7 @@ ruleTester.run('jsx-indent', rule, { } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -290,7 +290,7 @@ ruleTester.run('jsx-indent', rule, { <> ] `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -328,7 +328,7 @@ ruleTester.run('jsx-indent', rule, { }
`, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -349,7 +349,7 @@ ruleTester.run('jsx-indent', rule, { bar `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -366,7 +366,7 @@ ruleTester.run('jsx-indent', rule, { <> : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -383,7 +383,7 @@ ruleTester.run('jsx-indent', rule, { <> : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -402,7 +402,7 @@ ruleTester.run('jsx-indent', rule, { : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -432,7 +432,7 @@ ruleTester.run('jsx-indent', rule, { foo ? <> : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix }, { // Multiline ternary @@ -447,7 +447,7 @@ ruleTester.run('jsx-indent', rule, { foo ? <> : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix }, { // Multiline ternary @@ -464,7 +464,7 @@ ruleTester.run('jsx-indent', rule, { : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -483,7 +483,7 @@ ruleTester.run('jsx-indent', rule, { ) : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -502,7 +502,7 @@ ruleTester.run('jsx-indent', rule, { ) : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -523,7 +523,7 @@ ruleTester.run('jsx-indent', rule, { : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -542,7 +542,7 @@ ruleTester.run('jsx-indent', rule, { <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -563,7 +563,7 @@ ruleTester.run('jsx-indent', rule, { <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -584,7 +584,7 @@ ruleTester.run('jsx-indent', rule, { <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -605,7 +605,7 @@ ruleTester.run('jsx-indent', rule, { <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -628,7 +628,7 @@ ruleTester.run('jsx-indent', rule, { <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -653,7 +653,7 @@ ruleTester.run('jsx-indent', rule, { <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -670,7 +670,7 @@ ruleTester.run('jsx-indent', rule, { <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -685,7 +685,7 @@ ruleTester.run('jsx-indent', rule, { foo ? <> : (<>) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { // Multiline ternary @@ -704,7 +704,7 @@ ruleTester.run('jsx-indent', rule, { <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -760,7 +760,7 @@ ruleTester.run('jsx-indent', rule, { } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -772,7 +772,7 @@ ruleTester.run('jsx-indent', rule, { }} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -783,7 +783,7 @@ ruleTester.run('jsx-indent', rule, { })} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -798,7 +798,7 @@ ruleTester.run('jsx-indent', rule, { }} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -813,7 +813,7 @@ ruleTester.run('jsx-indent', rule, { })} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -823,7 +823,7 @@ ruleTester.run('jsx-indent', rule, { }} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -833,7 +833,7 @@ ruleTester.run('jsx-indent', rule, { })} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -844,7 +844,7 @@ ruleTester.run('jsx-indent', rule, { }} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -855,7 +855,7 @@ ruleTester.run('jsx-indent', rule, { })} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -867,7 +867,7 @@ ruleTester.run('jsx-indent', rule, { }} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -879,7 +879,7 @@ ruleTester.run('jsx-indent', rule, { })} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], }, { code: ` @@ -909,7 +909,7 @@ ruleTester.run('jsx-indent', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [2], }, { @@ -1094,9 +1094,9 @@ const Component = () => ( } `, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: `
@@ -1182,7 +1182,7 @@ const Component = () => ( <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` <> @@ -1206,7 +1206,7 @@ const Component = () => ( `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: ` <> @@ -1531,7 +1531,7 @@ const Component = () => ( <> ] `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` [
, @@ -1704,7 +1704,7 @@ const Component = () => ( : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` foo ? : @@ -1779,7 +1779,7 @@ const Component = () => ( : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` foo ? @@ -1857,7 +1857,7 @@ const Component = () => ( ) : <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` foo ? ( @@ -1939,7 +1939,7 @@ const Component = () => ( <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` foo ? : ( @@ -2024,7 +2024,7 @@ const Component = () => ( <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` foo ? @@ -2090,7 +2090,7 @@ const Component = () => ( <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` foo ? ( <> @@ -2211,7 +2211,7 @@ const Component = () => ( <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` foo ? ( <> @@ -2273,7 +2273,7 @@ const Component = () => ( <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` foo ? : ( <> @@ -2325,7 +2325,7 @@ const Component = () => ( <> ) `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix output: ` foo ? : ( @@ -2500,7 +2500,7 @@ const Component = () => ( }} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], errors: [ { messageId: 'wrongIndent', @@ -2530,7 +2530,7 @@ const Component = () => ( })} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], errors: [ { messageId: 'wrongIndent', @@ -2551,7 +2551,7 @@ const Component = () => ( }} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], output: ` {do { @@ -2586,7 +2586,7 @@ const Component = () => ( })} `, - parser: parsers.BABEL_ESLINT, + features: ['do expressions'], errors: [ { messageId: 'wrongIndent', @@ -2696,7 +2696,6 @@ const Component = () => ( \t\ttext
`, - parser: parsers.BABEL_ESLINT, options: ['tab'], output: `
@@ -2721,7 +2720,7 @@ const Component = () => ( aaa `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: ` <> aaa @@ -2739,5 +2738,5 @@ const Component = () => ( }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-key.js b/tests/lib/rules/jsx-key.js index cc55352070..bb0b13e5e3 100644 --- a/tests/lib/rules/jsx-key.js +++ b/tests/lib/rules/jsx-key.js @@ -35,7 +35,7 @@ const settings = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-key', rule, { - valid: [ + valid: parsers.all([ { code: 'fn()' }, { code: '[1, 2, 3].map(function () {})' }, { code: ';' }, @@ -49,38 +49,25 @@ ruleTester.run('jsx-key', rule, { { code: 'foo(() =>
);' }, { code: 'foo(() => <>);', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '<>;', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ';', - parser: parsers.BABEL_ESLINT, }, { code: ';', - parser: parsers.BABEL_ESLINT, - options: [{ checkKeyMustBeforeSpread: true }], - }, - { - code: ';', - parser: parsers.TYPESCRIPT_ESLINT, options: [{ checkKeyMustBeforeSpread: true }], }, { code: '
;', - parser: parsers.BABEL_ESLINT, options: [{ checkKeyMustBeforeSpread: true }], }, - { - code: '
;', - parser: parsers.TYPESCRIPT_ESLINT, - options: [{ checkKeyMustBeforeSpread: true }], - }, - ], - invalid: [].concat( + ]), + invalid: parsers.all([ { code: '[];', errors: [{ messageId: 'missingArrayKey' }], @@ -107,19 +94,17 @@ ruleTester.run('jsx-key', rule, { }, { code: '[1, 2, 3]?.map(x => )', - parser: parsers.BABEL_ESLINT, + features: ['no-default'], + errors: [{ messageId: 'missingIterKey' }], + }, + { + code: '[1, 2, 3]?.map(x => )', + features: ['ts'], errors: [{ messageId: 'missingIterKey' }], }, - parsers.TS([ - { - code: '[1, 2, 3]?.map(x => )', - parser: parsers['@TYPESCRIPT_ESLINT'], - errors: [{ messageId: 'missingIterKey' }], - }, - ]), { code: '[1, 2, 3].map(x => <>{x});', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ checkFragmentShorthand: true }], settings, errors: [ @@ -134,7 +119,7 @@ ruleTester.run('jsx-key', rule, { }, { code: '[<>];', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ checkFragmentShorthand: true }], settings, errors: [ @@ -149,31 +134,15 @@ ruleTester.run('jsx-key', rule, { }, { code: '[];', - parser: parsers.BABEL_ESLINT, - options: [{ checkKeyMustBeforeSpread: true }], - settings, - errors: [{ messageId: 'keyBeforeSpread' }], - }, - { - code: '[];', - parser: parsers.TYPESCRIPT_ESLINT, options: [{ checkKeyMustBeforeSpread: true }], settings, errors: [{ messageId: 'keyBeforeSpread' }], }, { code: '[
];', - parser: parsers.BABEL_ESLINT, options: [{ checkKeyMustBeforeSpread: true }], settings, errors: [{ messageId: 'keyBeforeSpread' }], }, - { - code: '[
];', - parser: parsers.TYPESCRIPT_ESLINT, - options: [{ checkKeyMustBeforeSpread: true }], - settings, - errors: [{ messageId: 'keyBeforeSpread' }], - } - ), + ]), }); diff --git a/tests/lib/rules/jsx-max-depth.js b/tests/lib/rules/jsx-max-depth.js index f3d37a469f..2aefb31e95 100644 --- a/tests/lib/rules/jsx-max-depth.js +++ b/tests/lib/rules/jsx-max-depth.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-max-depth', rule, { - valid: [ + valid: parsers.all([ { code: ` @@ -76,7 +76,7 @@ ruleTester.run('jsx-max-depth', rule, { code: ` <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -84,7 +84,7 @@ ruleTester.run('jsx-max-depth', rule, { `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ max: 1 }], }, { @@ -92,7 +92,7 @@ ruleTester.run('jsx-max-depth', rule, { const x = <>x; <>{x} `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ max: 2 }], }, { @@ -155,9 +155,9 @@ ruleTester.run('jsx-max-depth', rule, { }; `, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` @@ -253,7 +253,6 @@ ruleTester.run('jsx-max-depth', rule, { {
}
`, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'wrongDepth', @@ -267,7 +266,7 @@ ruleTester.run('jsx-max-depth', rule, { `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ max: 0 }], errors: [ { @@ -284,7 +283,7 @@ ruleTester.run('jsx-max-depth', rule, { `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ max: 1 }], errors: [ { @@ -299,7 +298,7 @@ ruleTester.run('jsx-max-depth', rule, { let y = x; <>{x}-{y} `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ max: 1 }], errors: [ { @@ -362,5 +361,5 @@ ruleTester.run('jsx-max-depth', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-max-props-per-line.js b/tests/lib/rules/jsx-max-props-per-line.js index 4b29d8d9a6..356898242f 100644 --- a/tests/lib/rules/jsx-max-props-per-line.js +++ b/tests/lib/rules/jsx-max-props-per-line.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-max-props-per-line'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-max-props-per-line', rule, { - valid: [ + valid: parsers.all([ { code: '', }, @@ -142,9 +144,9 @@ ruleTester.run('jsx-max-props-per-line', rule, { `, options: [{ maximum: 1, when: 'multiline' }], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` ; @@ -533,5 +535,5 @@ baz bor }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-newline.js b/tests/lib/rules/jsx-newline.js index 2be3f584df..68d1ff25ba 100644 --- a/tests/lib/rules/jsx-newline.js +++ b/tests/lib/rules/jsx-newline.js @@ -26,34 +26,79 @@ const parserOptions = { // Tests // ------------------------------------------------------------------------------ -const tests = { - valid: [ - ` -
- +new RuleTester({ parserOptions }).run('jsx-newline', rule, { + valid: parsers.all([ + { + code: ` +
+ - + + + - - + {showSomething === true && } - {showSomething === true && } + - + {showSomethingElse === true ? ( + + ) : ( + + )} +
+ `, + }, + { + code: ` +
+ + + + {showSomething === true && } + + {showSomethingElse === true ? ( + + ) : ( + + )} +
+ `, + options: [{ prevent: true }], + }, + { + code: ` + <> + + Test - {showSomethingElse === true ? ( - - ) : ( - - )} -
- `, - ], - invalid: [ + Should be in new line + + `, + features: ['fragment'], + }, + { + code: ` + <> + + Test + Should be in new line + + `, + options: [{ prevent: true }], + features: ['fragment'], + }, + ]), + invalid: parsers.all([ { code: `
@@ -162,96 +207,6 @@ const tests = { { messageId: 'require' }, ], }, - ], -}; - -const advanceFeatTest = { - valid: [ - { - code: ` - <> - - Test - - Should be in new line - - `, - }, - ], - invalid: [ - { - code: ` - <> - - Test - Should be in new line - - `, - output: ` - <> - - Test - - Should be in new line - - `, - errors: [{ messageId: 'require' }], - }, - ], -}; - -// Run tests with default parser -new RuleTester({ parserOptions }).run('jsx-newline', rule, tests); - -// Run tests with babel parser -let ruleTester = new RuleTester({ parserOptions, parser: parsers.BABEL_ESLINT }); -ruleTester.run('jsx-newline', rule, tests); -ruleTester.run('jsx-newline', rule, advanceFeatTest); - -// Run tests with typescript parser -ruleTester = new RuleTester({ parserOptions, parser: parsers.TYPESCRIPT_ESLINT }); -ruleTester.run('jsx-newline', rule, tests); -ruleTester.run('jsx-newline', rule, advanceFeatTest); - -ruleTester = new RuleTester({ parserOptions, parser: parsers['@TYPESCRIPT_ESLINT'] }); -ruleTester.run('jsx-newline', rule, { - valid: parsers.TS(tests.valid), - invalid: parsers.TS(tests.invalid), -}); -ruleTester.run('jsx-newline', rule, { - valid: parsers.TS(advanceFeatTest.valid), - invalid: parsers.TS(advanceFeatTest.invalid), -}); - -// ------------------------------------------------------------------------------ -// Tests: { prevent: true } -// --------- --------------------------------------------------------------------- - -const preventionTests = { - valid: [ - { - code: ` -
- - - - {showSomething === true && } - - {showSomethingElse === true ? ( - - ) : ( - - )} -
- `, - options: [{ prevent: true }], - }, - ], - invalid: [ { output: `
@@ -363,11 +318,6 @@ const preventionTests = { ], options: [{ prevent: true }], }, - ], -}; - -const preventionAdvanceFeatTest = { - valid: [ { code: ` <> @@ -376,10 +326,17 @@ const preventionAdvanceFeatTest = { Should be in new line `, - options: [{ prevent: true }], + output: ` + <> + + Test + + Should be in new line + + `, + errors: [{ messageId: 'require' }], + features: ['fragment'], }, - ], - invalid: [ { output: ` <> @@ -398,29 +355,7 @@ const preventionAdvanceFeatTest = { `, errors: [{ messageId: 'prevent' }], options: [{ prevent: true }], + features: ['fragment'], }, - ], -}; - -// // Run tests with default parser -new RuleTester({ parserOptions }).run('jsx-newline', rule, preventionTests); - -// // Run tests with babel parser -ruleTester = new RuleTester({ parserOptions, parser: parsers.BABEL_ESLINT }); -ruleTester.run('jsx-newline', rule, preventionTests); -ruleTester.run('jsx-newline', rule, preventionAdvanceFeatTest); - -// // Run tests with typescript parser -ruleTester = new RuleTester({ parserOptions, parser: parsers.TYPESCRIPT_ESLINT }); -ruleTester.run('jsx-newline', rule, preventionTests); -ruleTester.run('jsx-newline', rule, preventionAdvanceFeatTest); - -ruleTester = new RuleTester({ parserOptions, parser: parsers['@TYPESCRIPT_ESLINT'] }); -ruleTester.run('jsx-newline', rule, { - valid: parsers.TS(preventionTests.valid), - invalid: parsers.TS(preventionTests.invalid), -}); -ruleTester.run('jsx-newline', rule, { - valid: parsers.TS(preventionAdvanceFeatTest.valid), - invalid: parsers.TS(preventionAdvanceFeatTest.invalid), + ]), }); diff --git a/tests/lib/rules/jsx-no-bind.js b/tests/lib/rules/jsx-no-bind.js index 47c4cccc9e..4dec6b3c59 100644 --- a/tests/lib/rules/jsx-no-bind.js +++ b/tests/lib/rules/jsx-no-bind.js @@ -29,7 +29,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-no-bind', rule, { - valid: [ + valid: parsers.all([ // Not covered by the rule { code: '
', @@ -202,7 +202,7 @@ ruleTester.run('jsx-no-bind', rule, { } }; `, - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: ` @@ -214,7 +214,7 @@ ruleTester.run('jsx-no-bind', rule, { } }; `, - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: ` @@ -236,7 +236,7 @@ ruleTester.run('jsx-no-bind', rule, { } }); `, - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: ` @@ -257,7 +257,7 @@ ruleTester.run('jsx-no-bind', rule, { } }; `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -269,7 +269,7 @@ ruleTester.run('jsx-no-bind', rule, { } }; `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { // issue #1543: don't crash on uninitialized variables @@ -299,7 +299,7 @@ ruleTester.run('jsx-no-bind', rule, { { code: '
', options: [{ ignoreDOMComponents: true }], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, // Local function declaration @@ -314,9 +314,9 @@ ruleTester.run('jsx-no-bind', rule, { `, errors: [], }, - ], + ]), - invalid: [ + invalid: parsers.all([ // .bind() { code: '
', @@ -377,7 +377,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'bindCall' }], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -389,7 +389,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'bindCall' }], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -439,7 +439,7 @@ ruleTester.run('jsx-no-bind', rule, { { messageId: 'bindCall' }, { messageId: 'arrowFunc' }, ], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -513,7 +513,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'arrowFunc' }], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -525,7 +525,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'arrowFunc' }], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -537,7 +537,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'arrowFunc' }], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -598,7 +598,7 @@ ruleTester.run('jsx-no-bind', rule, { { messageId: 'arrowFunc' }, { messageId: 'bindExpression' }, ], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, // Functions @@ -628,7 +628,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'func' }], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -640,7 +640,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'func' }], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -652,7 +652,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'func' }], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -664,7 +664,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'func' }], - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove "no-ts-old" }, { code: ` @@ -746,24 +746,24 @@ ruleTester.run('jsx-no-bind', rule, { { messageId: 'func' }, { messageId: 'bindExpression' }, ], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, // Bind expression { code: '
', errors: [{ messageId: 'bindExpression' }], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: '
', errors: [{ messageId: 'bindExpression' }], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: '
', errors: [{ messageId: 'bindExpression' }], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: ` @@ -775,7 +775,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'bindExpression' }], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: ` @@ -787,7 +787,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'bindExpression' }], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: ` @@ -799,7 +799,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'bindExpression' }], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, { code: ` @@ -815,7 +815,7 @@ ruleTester.run('jsx-no-bind', rule, { }; `, errors: [{ messageId: 'bindExpression' }], - parser: parsers.BABEL_ESLINT, + features: ['bind operator'], }, // Local function declaration @@ -839,5 +839,5 @@ ruleTester.run('jsx-no-bind', rule, { options: [{ ignoreDOMComponents: true }], errors: [{ messageId: 'bindCall' }], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-no-comment-textnodes.js b/tests/lib/rules/jsx-no-comment-textnodes.js index 4cf8eb031f..089c3d8560 100644 --- a/tests/lib/rules/jsx-no-comment-textnodes.js +++ b/tests/lib/rules/jsx-no-comment-textnodes.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-no-comment-textnodes', rule, { - valid: [ + valid: parsers.all([ { code: ` class Comp1 extends Component { @@ -41,7 +41,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -55,7 +54,7 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -65,7 +64,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -76,7 +74,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -87,7 +84,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { }, }); `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -103,7 +99,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -116,13 +111,11 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` var foo = require('foo'); `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -130,7 +123,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { {/* valid */} `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -138,7 +130,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, {  https://www.example.com/attachment/download/1 `, - parser: parsers.BABEL_ESLINT, }, // inside element declarations @@ -146,177 +137,33 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { code: ` `, - parser: parsers.BABEL_ESLINT, }, { code: ` `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` <> `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts'], // TODO: FIXME: figure out why both TS parsers fail on this }, { code: ` `, - parser: parsers.BABEL_ESLINT, }, { code: '
// TODO: Write perfect code
', }, - { - code: '
// TODO: Write perfect code
', - parser: parsers.BABEL_ESLINT, - }, { code: '
/* TODO: Write perfect code */
', }, - { - code: '
/* TODO: Write perfect code */
', - parser: parsers.BABEL_ESLINT, - }, - ].concat(parsers.TS([ - { - code: ` - class Comp1 extends Component { - render() { - return ( -
- {/* valid */} -
- ); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - class Comp1 extends Component { - render() { - return ( - <> - {/* valid */} - - ); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - class Comp1 extends Component { - render() { - return (
{/* valid */}
); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - class Comp1 extends Component { - render() { - const bar = (
{/* valid */}
); - return bar; - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - var Hello = createReactClass({ - foo: (
{/* valid */}
), - render() { - return this.foo; - }, - }); - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - class Comp1 extends Component { - render() { - return ( -
- {/* valid */} - {/* valid 2 */} - {/* valid 3 */} -
- ); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - class Comp1 extends Component { - render() { - return ( -
-
- ); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - var foo = require('foo'); - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - - {/* valid */} - - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - -  https://www.example.com/attachment/download/1 - - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, + ]), - // inside element declarations - { - code: ` - - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: ` - - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: '
// TODO: Write perfect code
', - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - { - code: '
/* TODO: Write perfect code */
', - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - ])), - - invalid: [ + invalid: parsers.all([ { code: ` class Comp1 extends Component { @@ -325,7 +172,7 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['no-ts-old'], // TODO: FIXME: remove this and figure out why the old TS parser hangs here errors: [{ messageId: 'putCommentInBraces' }], }, { @@ -336,7 +183,7 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove this and figure out why the old TS parser hangs here errors: [{ messageId: 'putCommentInBraces' }], }, { @@ -347,7 +194,7 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['no-ts-old'], // TODO: FIXME: remove this and figure out why the old TS parser hangs here errors: [{ messageId: 'putCommentInBraces' }], }, { @@ -362,7 +209,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [{ messageId: 'putCommentInBraces' }], }, { @@ -379,7 +225,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [{ messageId: 'putCommentInBraces' }], }, { @@ -396,7 +241,6 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [{ messageId: 'putCommentInBraces' }], }, { @@ -405,90 +249,8 @@ ruleTester.run('jsx-no-comment-textnodes', rule, { return /*; }; `, + features: ['no-ts-old'], // TODO: FIXME: remove this and figure out why the old TS parser hangs here errors: [{ messageId: 'putCommentInBraces' }], }, - ].concat(parsers.TS([ - { - code: ` - class Comp1 extends Component { - render() { - return (
// invalid
); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - errors: [{ messageId: 'putCommentInBraces' }], - }, - { - code: ` - class Comp1 extends Component { - render() { - return (<>// invalid); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - errors: [{ messageId: 'putCommentInBraces' }], - }, - { - code: ` - class Comp1 extends Component { - render() { - return (
/* invalid */
); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - errors: [{ messageId: 'putCommentInBraces' }], - }, - { - code: ` - class Comp1 extends Component { - render() { - return ( -
- // invalid -
- ); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - errors: [{ messageId: 'putCommentInBraces' }], - }, - { - code: ` - class Comp1 extends Component { - render() { - return ( -
- asdjfl - /* invalid */ - foo -
- ); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - errors: [{ messageId: 'putCommentInBraces' }], - }, - { - code: ` - class Comp1 extends Component { - render() { - return ( -
- {'asdjfl'} - // invalid - {'foo'} -
- ); - } - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - errors: [{ messageId: 'putCommentInBraces' }], - }, - ])), + ]), }); diff --git a/tests/lib/rules/jsx-no-constructed-context-values.js b/tests/lib/rules/jsx-no-constructed-context-values.js index 74917d1036..7a59da820c 100644 --- a/tests/lib/rules/jsx-no-constructed-context-values.js +++ b/tests/lib/rules/jsx-no-constructed-context-values.js @@ -29,7 +29,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('react-no-constructed-context-values', rule, { - valid: [].concat( + valid: parsers.all([ { code: '', }, @@ -62,7 +62,10 @@ ruleTester.run('react-no-constructed-context-values', rule, { ) } `, - parser: parsers.BABEL_ESLINT, + features: ['optional chaining'], + parserOptions: { + ecmaVersion: 2020, + }, }, { code: ` @@ -106,26 +109,8 @@ ruleTester.run('react-no-constructed-context-values', rule, { } `, }, - parsers.TS([ - { - code: ` - import React from 'react'; - import MyContext from './MyContext'; - - const value = ''; - - function ContextProvider(props) { - return ( - - {props.children} - - ) - } - `, - parser: parsers.TYPESCRIPT_ESLINT, - }, - { - code: ` + { + code: ` import React from 'react'; import MyContext from './MyContext'; @@ -139,9 +124,8 @@ ruleTester.run('react-no-constructed-context-values', rule, { ) } `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - ]), + features: ['types', 'no-babel'], + }, { code: ` import React from 'react'; @@ -155,9 +139,9 @@ ruleTester.run('react-no-constructed-context-values', rule, { ) } `, - } - ), - invalid: [ + }, + ]), + invalid: parsers.all([ { // Invalid because object construction creates a new identity code: 'function Component() { const foo = {}; return () }', @@ -411,7 +395,6 @@ ruleTester.run('react-no-constructed-context-values', rule, { }, }, ], - parser: parsers.BABEL_ESLINT, }, { // Invalid because inline object construction will create a new identity @@ -478,5 +461,5 @@ ruleTester.run('react-no-constructed-context-values', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-no-duplicate-props.js b/tests/lib/rules/jsx-no-duplicate-props.js index ac9f37b8d6..81f2508d92 100644 --- a/tests/lib/rules/jsx-no-duplicate-props.js +++ b/tests/lib/rules/jsx-no-duplicate-props.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-no-duplicate-props'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -36,7 +38,7 @@ const ignoreCaseArgs = [{ }]; ruleTester.run('jsx-no-duplicate-props', rule, { - valid: [ + valid: parsers.all([ { code: ';' }, { code: ';' }, { code: ';' }, @@ -52,9 +54,10 @@ ruleTester.run('jsx-no-duplicate-props', rule, { { code: ';', options: ignoreCaseArgs, + features: ['jsx namespace'], }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: ';', errors: [expectedError], @@ -82,5 +85,5 @@ ruleTester.run('jsx-no-duplicate-props', rule, { options: ignoreCaseArgs, errors: [expectedError], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-no-literals.js b/tests/lib/rules/jsx-no-literals.js index 7cb4fb5bb2..d1cbcecb77 100644 --- a/tests/lib/rules/jsx-no-literals.js +++ b/tests/lib/rules/jsx-no-literals.js @@ -29,7 +29,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-no-literals', rule, { - valid: [].concat( + valid: parsers.all([ { code: ` class Comp1 extends Component { @@ -49,58 +49,6 @@ ruleTester.run('jsx-no-literals', rule, { }, ], }, - { - code: ` - class Comp1 extends Component { - render() { - return ( -
- -
- ); - } - } - `, - options: [ - { - noStrings: true, - allowedStrings: ['button', 'submit'], - }, - ], - parser: parsers.BABEL_ESLINT, - }, - parsers.TS([ - { - code: ` - class Comp1 extends Component { - render() { - return ( -
- -
- ); - } - } - `, - options: [{ noStrings: true, allowedStrings: ['button', 'submit'] }], - parser: parsers.TYPESCRIPT_ESLINT, - }, - { - code: ` - class Comp2 extends Component { - render() { - return ( -
- -
- ); - } - } - `, - options: [{ noStrings: true, allowedStrings: ['button', 'submit'] }], - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - ]), { code: ` class Comp2 extends Component { @@ -113,7 +61,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -127,7 +74,7 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -137,7 +84,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -148,7 +94,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -159,7 +104,6 @@ ruleTester.run('jsx-no-literals', rule, { }, }); `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -175,7 +119,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -188,13 +131,11 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, }, { code: ` var foo = require('foo'); `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -202,25 +143,6 @@ ruleTester.run('jsx-no-literals', rule, { {'blarg'}
`, - parser: parsers.BABEL_ESLINT, - }, - { - code: ` - - {intl.formatText(message)} - - `, - parser: parsers.BABEL_ESLINT, - options: [{ noStrings: true, ignoreProps: true }], - }, - { - code: ` - - {translate('my.translate.key')} - - `, - parser: parsers.BABEL_ESLINT, - options: [{ noStrings: true, ignoreProps: true }], }, { code: ` @@ -353,18 +275,18 @@ ruleTester.run('jsx-no-literals', rule, { return ; } - } `, - parser: parsers.BABEL_ESLINT, + } + `, options: [{ noStrings: true, ignoreProps: false }], }, { code: ` blank image `, - } - ), + }, + ]), - invalid: [ + invalid: parsers.all([ { code: ` class Comp1 extends Component { @@ -373,7 +295,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'literalNotInJSXExpression', @@ -389,7 +310,7 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], errors: [ { messageId: 'literalNotInJSXExpression', @@ -406,7 +327,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'literalNotInJSXExpression', @@ -423,7 +343,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'literalNotInJSXExpression', @@ -440,7 +359,6 @@ ruleTester.run('jsx-no-literals', rule, { }, }); `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'literalNotInJSXExpression', @@ -460,7 +378,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'literalNotInJSXExpression', @@ -482,7 +399,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'literalNotInJSXExpression', @@ -508,7 +424,6 @@ ruleTester.run('jsx-no-literals', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'literalNotInJSXExpression', @@ -698,5 +613,5 @@ ruleTester.run('jsx-no-literals', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-no-script-url.js b/tests/lib/rules/jsx-no-script-url.js index af6211a087..24cff790a2 100644 --- a/tests/lib/rules/jsx-no-script-url.js +++ b/tests/lib/rules/jsx-no-script-url.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-no-script-url'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -27,7 +29,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-no-script-url', rule, { - valid: [ + valid: parsers.all([ { code: '' }, { code: '' }, { code: '' }, @@ -36,8 +38,8 @@ ruleTester.run('jsx-no-script-url', rule, { { code: '' }, { code: '' }, { code: '' }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: '', errors: [{ messageId: 'noScriptURL' }], @@ -82,5 +84,5 @@ ruleTester.run('jsx-no-script-url', rule, { ], ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-no-target-blank.js b/tests/lib/rules/jsx-no-target-blank.js index 563a66ee7c..65067fee7c 100644 --- a/tests/lib/rules/jsx-no-target-blank.js +++ b/tests/lib/rules/jsx-no-target-blank.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-no-target-blank'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -28,7 +30,7 @@ const ruleTester = new RuleTester({ parserOptions }); const defaultErrors = [{ messageId: 'noTargetBlankWithoutNoreferrer' }]; ruleTester.run('jsx-no-target-blank', rule, { - valid: [ + valid: parsers.all([ { code: '' }, { code: '' }, { code: '' }, @@ -139,8 +141,8 @@ ruleTester.run('jsx-no-target-blank', rule, { { code: '', }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: '', output: '', @@ -344,5 +346,5 @@ ruleTester.run('jsx-no-target-blank', rule, { options: [{ forms: true, links: false }], errors: defaultErrors, }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-no-undef.js b/tests/lib/rules/jsx-no-undef.js index 1ff5e49273..0cadc5cb27 100644 --- a/tests/lib/rules/jsx-no-undef.js +++ b/tests/lib/rules/jsx-no-undef.js @@ -32,14 +32,10 @@ const linter = ruleTester.linter || eslint.linter; linter.defineRule('no-undef', require('eslint/lib/rules/no-undef')); ruleTester.run('jsx-no-undef', rule, { - valid: [ + valid: parsers.all([ { code: '/*eslint no-undef:1*/ var React, App; React.render();', }, - { - code: '/*eslint no-undef:1*/ var React, App; React.render();', - parser: parsers.BABEL_ESLINT, - }, { code: '/*eslint no-undef:1*/ var React; React.render();', }, @@ -54,6 +50,7 @@ ruleTester.run('jsx-no-undef', rule, { }, { code: '/*eslint no-undef:1*/ var React; React.render();', + features: ['jsx namespace'], }, { code: ` @@ -71,6 +68,7 @@ ruleTester.run('jsx-no-undef', rule, { globals: { Text: true, }, + features: ['no-babel'], // TODO: FIXME: remove `no-babel` and fix }, { code: ` @@ -83,11 +81,10 @@ ruleTester.run('jsx-no-undef', rule, { `, parserOptions: Object.assign({ sourceType: 'module' }, parserOptions), options: [{ allowGlobals: false }], - parser: parsers.BABEL_ESLINT, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: '/*eslint no-undef:1*/ var React; React.render();', errors: [ @@ -141,7 +138,6 @@ ruleTester.run('jsx-no-undef', rule, { }, ], options: [{ allowGlobals: false }], - parser: parsers.BABEL_ESLINT, globals: { Text: true, }, @@ -155,5 +151,5 @@ ruleTester.run('jsx-no-undef', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-no-useless-fragment.js b/tests/lib/rules/jsx-no-useless-fragment.js index 5e4fc7b416..6b104dd976 100644 --- a/tests/lib/rules/jsx-no-useless-fragment.js +++ b/tests/lib/rules/jsx-no-useless-fragment.js @@ -28,22 +28,22 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-no-useless-fragment', rule, { - valid: [ + valid: parsers.all([ { code: '<>', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '<>foo
', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '<>
', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '<>{"moo"} ', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '', @@ -56,27 +56,26 @@ ruleTester.run('jsx-no-useless-fragment', rule, { }, { code: '<>
', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '
{"a"}{"b"}} />', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '{item.value}', - parser: parsers.BABEL_ESLINT, }, { code: 'eeee ee eeeeeee eeeeeeee} />', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '<>{foos.map(foo => foo)}', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '<>{moo}', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ allowExpressions: true }], }, { @@ -85,46 +84,46 @@ ruleTester.run('jsx-no-useless-fragment', rule, { {moo} `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ allowExpressions: true }], }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: '<>', output: null, errors: [{ messageId: 'NeedsMoreChildren', type: 'JSXFragment' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '<>{}', output: null, errors: [{ messageId: 'NeedsMoreChildren', type: 'JSXFragment' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '

moo<>foo

', output: '

moofoo

', errors: [{ messageId: 'NeedsMoreChildren' }, { messageId: 'ChildOfHtmlElement' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, { code: '<>{meow}', output: null, errors: [{ messageId: 'NeedsMoreChildren' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: '

<>{meow}

', output: '

{meow}

', errors: [{ messageId: 'NeedsMoreChildren' }, { messageId: 'ChildOfHtmlElement' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, { code: '<>
', output: '
', errors: [{ messageId: 'NeedsMoreChildren' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, { code: ` @@ -136,7 +135,7 @@ ruleTester.run('jsx-no-useless-fragment', rule, {
`, errors: [{ messageId: 'NeedsMoreChildren' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, { code: '', @@ -172,19 +171,25 @@ ruleTester.run('jsx-no-useless-fragment', rule, { code: '<>foo', output: null, errors: [{ messageId: 'NeedsMoreChildren' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, { code: '
<>foo
', output: '
foo
', errors: [{ messageId: 'NeedsMoreChildren' }, { messageId: 'ChildOfHtmlElement' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, { code: '
<>{"a"}{"b"}
', output: '
{"a"}{"b"}
', errors: [{ messageId: 'ChildOfHtmlElement' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and next test case + }, + { + code: '
<>{"a"}{"b"}
', + output: '
<>{"a"}{"b"}
', + errors: [{ messageId: 'ChildOfHtmlElement' }], + features: ['fragment', 'ts-old', 'no-ts-new', 'no-babel', 'no-default'], }, { code: ` @@ -200,7 +205,7 @@ ruleTester.run('jsx-no-useless-fragment', rule, { {"a"}{"b"} `, errors: [{ messageId: 'ChildOfHtmlElement' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, { code: '
{"a"}{"b"}
', @@ -224,13 +229,13 @@ ruleTester.run('jsx-no-useless-fragment', rule, { git hub `, errors: [{ messageId: 'ChildOfHtmlElement' }, { messageId: 'ChildOfHtmlElement' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, { code: '
a <>{""}{""} a
', output: '
a {""}{""} a
', errors: [{ messageId: 'ChildOfHtmlElement' }], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, { code: ` @@ -255,7 +260,7 @@ ruleTester.run('jsx-no-useless-fragment', rule, { options: [{ allowExpressions: true }], errors: [{ messageId: 'NeedsMoreChildren' }], output: '{moo}', - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-one-expression-per-line.js b/tests/lib/rules/jsx-one-expression-per-line.js index 9341ce1c39..a8ba820d02 100644 --- a/tests/lib/rules/jsx-one-expression-per-line.js +++ b/tests/lib/rules/jsx-one-expression-per-line.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-one-expression-per-line', rule, { - valid: [ + valid: parsers.all([ { code: '', }, @@ -165,7 +165,7 @@ ruleTester.run('jsx-one-expression-per-line', rule, { }, { code: '<>', - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -173,7 +173,7 @@ ruleTester.run('jsx-one-expression-per-line', rule, { `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix }, { code: ` @@ -182,11 +182,11 @@ ruleTester.run('jsx-one-expression-per-line', rule, { `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` {"foo"} @@ -896,7 +896,6 @@ foo }, ], parserOptions, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -1316,7 +1315,7 @@ foo data: { descriptor: '{"foo"}' }, }, ], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix parserOptions, }, { @@ -1337,7 +1336,7 @@ foo data: { descriptor: '<>' }, }, ], - parser: parsers.BABEL_ESLINT, + features: ['fragment'], parserOptions, }, { @@ -1358,7 +1357,7 @@ foo data: { descriptor: 'Foo' }, }, ], - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts-old'], parserOptions, }, { @@ -1388,8 +1387,7 @@ a data: { descriptor: '{a}' }, }, ], - parser: parsers.BABEL_ESLINT, parserOptions, }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-pascal-case.js b/tests/lib/rules/jsx-pascal-case.js index 87af3c074b..9923131118 100644 --- a/tests/lib/rules/jsx-pascal-case.js +++ b/tests/lib/rules/jsx-pascal-case.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-pascal-case', rule, { - valid: [ + valid: parsers.all([ { // The rule must not warn on components that start with a lowercase // because they are interpreted as HTML elements by React @@ -73,10 +73,6 @@ ruleTester.run('jsx-pascal-case', rule, { { code: '', }, - { - code: '', - parser: parsers.BABEL_ESLINT, - }, { code: '', options: [{ allowAllCaps: true }], @@ -93,6 +89,7 @@ ruleTester.run('jsx-pascal-case', rule, { }, { code: '', + features: ['jsx namespace'], }, { code: '', @@ -130,9 +127,9 @@ ruleTester.run('jsx-pascal-case', rule, { code: '<_TestComponent />', options: [{ allowLeadingUnderscore: true }], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: '', errors: [ @@ -267,5 +264,5 @@ ruleTester.run('jsx-pascal-case', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-props-no-multi-spaces.js b/tests/lib/rules/jsx-props-no-multi-spaces.js index 1126e61c28..1f3597bbcf 100644 --- a/tests/lib/rules/jsx-props-no-multi-spaces.js +++ b/tests/lib/rules/jsx-props-no-multi-spaces.js @@ -30,7 +30,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-props-no-multi-spaces', rule, { - valid: [].concat( + valid: parsers.all([].concat( { code: ` @@ -73,7 +73,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, { }, { code: ' foo bar />', - parser: parsers.TYPESCRIPT_ESLINT, + features: ['ts', 'no-babel'], }, { code: '', @@ -150,9 +150,9 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, { `, }, ] : []) - ), + )), - invalid: [].concat( + invalid: parsers.all([].concat( { code: ` @@ -242,8 +242,12 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, { ], }, { - code: '', - output: '', + code: ` + + `, + output: ` + + `, errors: [ { messageId: 'onlyOneSpace', @@ -361,5 +365,6 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, { }, ], }, - ] : [])), + ] : []) + )), }); diff --git a/tests/lib/rules/jsx-props-no-spreading.js b/tests/lib/rules/jsx-props-no-spreading.js index d88c1535ed..27fbf37170 100644 --- a/tests/lib/rules/jsx-props-no-spreading.js +++ b/tests/lib/rules/jsx-props-no-spreading.js @@ -11,6 +11,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-props-no-spreading'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -27,7 +29,7 @@ const ruleTester = new RuleTester({ parserOptions }); const expectedError = { messageId: 'noSpreading' }; ruleTester.run('jsx-props-no-spreading', rule, { - valid: [ + valid: parsers.all([ { code: ` const {one_prop, two_prop} = props; @@ -134,9 +136,9 @@ ruleTester.run('jsx-props-no-spreading', rule, { }, ], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` @@ -261,5 +263,5 @@ ruleTester.run('jsx-props-no-spreading', rule, { options: [{ exceptions: ['components.DropdownIndicator', 'Nav.Item'] }], errors: [expectedError], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-sort-default-props.js b/tests/lib/rules/jsx-sort-default-props.js index c5abe23bfa..3ee48d8cc7 100644 --- a/tests/lib/rules/jsx-sort-default-props.js +++ b/tests/lib/rules/jsx-sort-default-props.js @@ -31,7 +31,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-sort-default-props', rule, { - valid: [].concat( + valid: parsers.all([].concat( { code: ` var First = createReactClass({ @@ -181,7 +181,7 @@ ruleTester.run('jsx-sort-default-props', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -197,7 +197,6 @@ ruleTester.run('jsx-sort-default-props', rule, { "aria-controls": "aria-controls" }; `, - parser: parsers.BABEL_ESLINT, options: [{ ignoreCase: true }], }, semver.satisfies(babelEslintVersion, '< 9') ? { @@ -268,7 +267,7 @@ ruleTester.run('jsx-sort-default-props', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -291,7 +290,7 @@ ruleTester.run('jsx-sort-default-props', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -313,7 +312,6 @@ ruleTester.run('jsx-sort-default-props', rule, { a: "a" }; `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -361,9 +359,9 @@ ruleTester.run('jsx-sort-default-props', rule, { First.defaultProps = defaultProps; `, } - ), + )), - invalid: [ + invalid: parsers.all([ { code: ` class Component extends React.Component { @@ -382,7 +380,7 @@ ruleTester.run('jsx-sort-default-props', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { messageId: 'propsNotSorted', @@ -444,7 +442,7 @@ ruleTester.run('jsx-sort-default-props', rule, { } } `, */ - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: 2, }, { @@ -478,7 +476,7 @@ ruleTester.run('jsx-sort-default-props', rule, { } } `, */ - parser: parsers.BABEL_ESLINT, + features: ['class fields'], options: [{ ignoreCase: true }], errors: [ { @@ -520,7 +518,7 @@ ruleTester.run('jsx-sort-default-props', rule, { } } `, */ - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { messageId: 'propsNotSorted', @@ -561,7 +559,6 @@ ruleTester.run('jsx-sort-default-props', rule, { "b": "b" }; `, */ - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'propsNotSorted', @@ -606,7 +603,6 @@ ruleTester.run('jsx-sort-default-props', rule, { "c": "c" }; `, */ - parser: parsers.BABEL_ESLINT, errors: 2, }, { @@ -640,7 +636,6 @@ ruleTester.run('jsx-sort-default-props', rule, { "a": "a", }; `, */ - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'propsNotSorted', @@ -669,7 +664,6 @@ ruleTester.run('jsx-sort-default-props', rule, { // "B": "B", // }; // `, - // parser: parsers.BABEL_ESLINT, // errors: [ // { // messageId: 'propsNotSorted', @@ -727,7 +721,6 @@ ruleTester.run('jsx-sort-default-props', rule, { "B": "B", }; `, */ - parser: parsers.BABEL_ESLINT, options: [{ ignoreCase: true }], errors: [ { @@ -803,7 +796,7 @@ ruleTester.run('jsx-sort-default-props', rule, { } } `, */ - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { messageId: 'propsNotSorted', @@ -854,7 +847,7 @@ ruleTester.run('jsx-sort-default-props', rule, { } } `, */ - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: 2, }, { @@ -896,7 +889,6 @@ ruleTester.run('jsx-sort-default-props', rule, { ...defaults, }; `, */ - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'propsNotSorted', @@ -906,5 +898,5 @@ ruleTester.run('jsx-sort-default-props', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-sort-props.js b/tests/lib/rules/jsx-sort-props.js index 0eff897260..8a9abe937f 100644 --- a/tests/lib/rules/jsx-sort-props.js +++ b/tests/lib/rules/jsx-sort-props.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-sort-props'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -89,7 +91,7 @@ const reservedFirstAsEmptyArrayArgs = [{ reservedFirst: [] }]; const reservedFirstAsInvalidArrayArgs = [{ reservedFirst: ['notReserved'] }]; ruleTester.run('jsx-sort-props', rule, { - valid: [ + valid: parsers.all([ { code: ';' }, { code: ';' }, { code: ';' }, @@ -154,8 +156,8 @@ ruleTester.run('jsx-sort-props', rule, { code: '', options: reservedFirstWithShorthandLast, }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: ';', errors: [expectedError], @@ -481,5 +483,5 @@ ruleTester.run('jsx-sort-props', rule, { options: reservedFirstAsInvalidArrayArgs, errors: [expectedInvalidReservedFirstError], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-space-before-closing.js b/tests/lib/rules/jsx-space-before-closing.js index b7879edd52..af69bd749a 100644 --- a/tests/lib/rules/jsx-space-before-closing.js +++ b/tests/lib/rules/jsx-space-before-closing.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-space-before-closing'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-space-before-closing', rule, { - valid: [ + valid: parsers.all([ { code: '', }, @@ -77,9 +79,9 @@ ruleTester.run('jsx-space-before-closing', rule, { `, options: ['never'], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: '', output: '', @@ -124,5 +126,5 @@ ruleTester.run('jsx-space-before-closing', rule, { options: ['never'], errors: [{ messageId: 'noSpaceBeforeClose' }], }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-tag-spacing.js b/tests/lib/rules/jsx-tag-spacing.js index 9ce3c27832..66899d6a90 100644 --- a/tests/lib/rules/jsx-tag-spacing.js +++ b/tests/lib/rules/jsx-tag-spacing.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/jsx-tag-spacing'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -76,7 +78,7 @@ function beforeClosingOptions(option) { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-tag-spacing', rule, { - valid: [ + valid: parsers.all([ { code: '', }, @@ -155,6 +157,7 @@ ruleTester.run('jsx-tag-spacing', rule, { { code: '< /App>', options: closingSlashOptions('always'), + features: ['no-ts'], }, { code: '

', @@ -171,6 +174,7 @@ ruleTester.run('jsx-tag-spacing', rule, { { code: '< App>', options: afterOpeningOptions('always'), + features: ['no-ts'], }, { code: '< App/>', @@ -253,9 +257,9 @@ ruleTester.run('jsx-tag-spacing', rule, { }, ], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: '', output: '', @@ -326,6 +330,7 @@ ruleTester.run('jsx-tag-spacing', rule, { output: '

;', errors: [{ messageId: 'closeSlashNoSpace' }], options: closingSlashOptions('never'), + features: ['no-ts'], }, { code: ` @@ -337,12 +342,14 @@ ruleTester.run('jsx-tag-spacing', rule, { `, errors: [{ messageId: 'closeSlashNoSpace' }], options: closingSlashOptions('never'), + features: ['no-ts'], }, { code: '', output: '< /App>', errors: [{ messageId: 'closeSlashNeedSpace' }], options: closingSlashOptions('always'), + features: ['no-ts'], }, { code: '

', @@ -477,5 +484,5 @@ ruleTester.run('jsx-tag-spacing', rule, { errors: [{ messageId: 'beforeCloseNeedSpace' }], options: beforeClosingOptions('always'), }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-uses-react.js b/tests/lib/rules/jsx-uses-react.js index b02b42ea07..1fdd0757e5 100644 --- a/tests/lib/rules/jsx-uses-react.js +++ b/tests/lib/rules/jsx-uses-react.js @@ -39,17 +39,25 @@ const linter = ruleTester.linter || eslint.linter; linter.defineRule('jsx-uses-react', require('../../../lib/rules/jsx-uses-react')); ruleTester.run('no-unused-vars', rule, { - valid: [].concat( + valid: parsers.all([ { code: '/*eslint jsx-uses-react:1*/ var React;

;' }, { code: '/*eslint jsx-uses-react:1*/ var React; (function () {
})();' }, { code: '/*eslint jsx-uses-react:1*/ /** @jsx Foo */ var Foo;
;' }, - { code: '/*eslint jsx-uses-react:1*/ var Foo;
;', settings }, - parsers.TS([ - { code: '/*eslint jsx-uses-react:1*/ var Frag; <>;', settings: { react: { fragment: 'Frag' } } }, - { code: '/*eslint jsx-uses-react:1*/ var React; <>;', parser: parsers.BABEL_ESLINT }, - ]) - ), - invalid: [].concat( + { + code: '/*eslint jsx-uses-react:1*/ var Foo;
;', + settings, + }, + { + code: '/*eslint jsx-uses-react:1*/ var Frag; <>;', + settings: { react: { fragment: 'Frag' } }, + features: ['fragment'], + }, + { + code: '/*eslint jsx-uses-react:1*/ var React; <>;', + features: ['fragment', 'no-ts-old'], // TODO: FIXME: fix for typescript-eslint + }, + ]), + invalid: parsers.all([ { code: '/*eslint jsx-uses-react:1*/ var React;', errors: [{ message: '\'React\' is defined but never used.' }], @@ -63,37 +71,17 @@ ruleTester.run('no-unused-vars', rule, { errors: [{ message: '\'React\' is defined but never used.' }], settings, }, - parsers.TS([ - { - code: '/*eslint jsx-uses-react:1*/ var Frag; <>;', - errors: [{ message: '\'Frag\' is defined but never used.' }], - parser: parsers.TYPESCRIPT_ESLINT, - settings: { react: { fragment: 'Fragment' } }, - }, - { - code: '/*eslint jsx-uses-react:1*/ var Frag; <>;', - errors: [{ message: '\'Frag\' is defined but never used.' }], - parser: parsers['@TYPESCRIPT_ESLINT'], - settings: { react: { fragment: 'Fragment' } }, - }, - { - code: '/*eslint jsx-uses-react:1*/ var React; <>;', - parser: parsers.BABEL_ESLINT, - errors: [{ message: '\'React\' is defined but never used.' }], - settings, - }, - { - code: '/*eslint jsx-uses-react:1*/ var React; <>;', - parser: parsers.TYPESCRIPT_ESLINT, - errors: [{ message: '\'React\' is defined but never used.' }], - settings, - }, - { - code: '/*eslint jsx-uses-react:1*/ var React; <>;', - parser: parsers['@TYPESCRIPT_ESLINT'], - errors: [{ message: '\'React\' is defined but never used.' }], - settings, - }, - ]) - ), + { + code: '/*eslint jsx-uses-react:1*/ var Frag; <>;', + errors: [{ message: '\'Frag\' is defined but never used.' }], + features: ['fragment'], + settings: { react: { fragment: 'Fragment' } }, + }, + { + code: '/*eslint jsx-uses-react:1*/ var React; <>;', + features: ['fragment'], + errors: [{ message: '\'React\' is defined but never used.' }], + settings, + }, + ]), }); diff --git a/tests/lib/rules/jsx-uses-vars.js b/tests/lib/rules/jsx-uses-vars.js index c7fce5be3b..d5e7073374 100644 --- a/tests/lib/rules/jsx-uses-vars.js +++ b/tests/lib/rules/jsx-uses-vars.js @@ -34,7 +34,7 @@ const linter = ruleTester.linter || eslint.linter; linter.defineRule('jsx-uses-vars', require('../../../lib/rules/jsx-uses-vars')); ruleTester.run('no-unused-vars', ruleNoUnusedVars, { - valid: [ + valid: parsers.all([ { code: ` /* eslint jsx-uses-vars: 1 */ @@ -53,14 +53,6 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { React.render(); `, }, - { - code: ` - /* eslint jsx-uses-vars: 1 */ - var App; - React.render(); - `, - parser: parsers.BABEL_ESLINT, - }, { code: ` /* eslint jsx-uses-vars: 1 */ @@ -140,8 +132,8 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { React.render(); `, }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: '/* eslint jsx-uses-vars: 1 */ var App;', errors: [{ message: '\'App\' is defined but never used.' }], @@ -166,6 +158,7 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { { message: '\'App\' is defined but never used.' }, { message: '\'Hello\' is defined but never used.' }, ], + features: ['jsx namespace'], }, { code: ` @@ -200,24 +193,6 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { }, ], }, - { - code: ` - /* eslint jsx-uses-vars: 1 */ - class HelloMessage { - render() { - var HelloMessage =
Hello
; - return HelloMessage; - } - } - `, - errors: [ - { - message: '\'HelloMessage\' is defined but never used.', - line: 3, - }, - ], - parser: parsers.BABEL_ESLINT, - }, { code: ` /* eslint jsx-uses-vars: 1 */ @@ -234,7 +209,6 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { line: 3, }, ], - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -258,15 +232,14 @@ ruleTester.run('no-unused-vars', ruleNoUnusedVars, { line: 3, }, ], - parser: parsers.BABEL_ESLINT, }, - ], + ]), }); // Check compatibility with eslint prefer-const rule (#716) ruleTester.run('prefer-const', rulePreferConst, { valid: [], - invalid: [ + invalid: parsers.all([ { code: ` /* eslint jsx-uses-vars:1 */ @@ -293,5 +266,5 @@ ruleTester.run('prefer-const', rulePreferConst, {
{filters}
; `, }, - ], + ]), }); diff --git a/tests/lib/rules/jsx-wrap-multilines.js b/tests/lib/rules/jsx-wrap-multilines.js index eb7f928899..e50fa9389b 100644 --- a/tests/lib/rules/jsx-wrap-multilines.js +++ b/tests/lib/rules/jsx-wrap-multilines.js @@ -626,28 +626,24 @@ function addNewLineSymbols(code) { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('jsx-wrap-multilines', rule, { - valid: [ + valid: parsers.all([ { code: RETURN_SINGLE_LINE, }, { code: RETURN_SINGLE_LINE_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: RETURN_PAREN, }, - { - code: RETURN_PAREN, - parser: parsers.BABEL_ESLINT, - }, { code: RETURN_SINGLE_LINE, options: [{ return: true }], }, { code: RETURN_SINGLE_LINE_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ return: true }], }, { @@ -667,7 +663,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: DECLARATION_TERNARY_SINGLE_LINE_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: DECLARATION_TERNARY_PAREN, @@ -676,11 +672,6 @@ ruleTester.run('jsx-wrap-multilines', rule, { code: DECLARATION_TERNARY_SINGLE_LINE, options: [{ declaration: true }], }, - { - code: DECLARATION_TERNARY_SINGLE_LINE, - parser: parsers.BABEL_ESLINT, - options: [{ declaration: true }], - }, { code: DECLARATION_TERNARY_PAREN, options: [{ declaration: true }], @@ -723,7 +714,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: DECLARATION_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: DECLARATION_SINGLE_LINE, @@ -739,7 +730,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: DECLARATION_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ declaration: 'ignore' }], }, { @@ -759,7 +750,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ASSIGNMENT_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ASSIGNMENT_PAREN, @@ -771,7 +762,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ASSIGNMENT_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ assignment: 'ignore' }], }, { @@ -783,7 +774,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ARROW_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ARROW_SINGLE_LINE, @@ -792,11 +783,6 @@ ruleTester.run('jsx-wrap-multilines', rule, { code: ARROW_PAREN, options: [{ arrow: true }], }, - { - code: ARROW_PAREN, - parser: parsers.BABEL_ESLINT, - options: [{ arrow: true }], - }, { code: ARROW_SINGLE_LINE, options: [{ arrow: true }], @@ -807,7 +793,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ARROW_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ arrow: 'ignore' }], }, { @@ -830,7 +816,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: CONDITION_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ condition: true }], }, { @@ -845,7 +831,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: LOGICAL_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ logical: true }], }, { @@ -860,7 +846,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ATTR_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ prop: true }], }, { @@ -869,7 +855,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: RETURN_PAREN_NEW_LINE_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], options: [{ return: 'parens-new-line' }], }, { @@ -904,9 +890,9 @@ ruleTester.run('jsx-wrap-multilines', rule, { code: ATTR_PAREN_NEW_LINE, options: [{ prop: 'parens-new-line' }], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: RETURN_NO_PAREN, output: RETURN_PAREN, @@ -914,7 +900,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: RETURN_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: RETURN_PAREN_FRAGMENT, errors: [{ messageId: 'missingParens' }], }, @@ -926,7 +912,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: RETURN_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: RETURN_PAREN_FRAGMENT, options: [{ return: true }], errors: [{ messageId: 'missingParens' }], @@ -941,7 +927,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: DECLARATION_TERNARY_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: DECLARATION_TERNARY_PAREN_FRAGMENT, errors: [ { messageId: 'missingParens' }, @@ -959,7 +945,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: DECLARATION_TERNARY_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: DECLARATION_TERNARY_PAREN_FRAGMENT, options: [{ declaration: true }], errors: [ @@ -977,7 +963,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ASSIGNMENT_TERNARY_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: ASSIGNMENT_TERNARY_PAREN_FRAGMENT, errors: [ { messageId: 'missingParens' }, @@ -995,7 +981,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ASSIGNMENT_TERNARY_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: ASSIGNMENT_TERNARY_PAREN_FRAGMENT, options: [{ assignment: true }], errors: [ @@ -1010,7 +996,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: DECLARATION_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: DECLARATION_PAREN_FRAGMENT, errors: [{ messageId: 'missingParens' }], }, @@ -1027,7 +1013,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ASSIGNMENT_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: ASSIGNMENT_PAREN_FRAGMENT, errors: [{ messageId: 'missingParens' }], }, @@ -1044,7 +1030,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ARROW_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: ARROW_PAREN_FRAGMENT, errors: [{ messageId: 'missingParens' }], }, @@ -1062,7 +1048,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: CONDITION_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: CONDITION_PAREN_FRAGMENT, options: [{ condition: 'parens' }], errors: [{ messageId: 'missingParens' }], @@ -1081,7 +1067,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: LOGICAL_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: LOGICAL_PAREN_FRAGMENT, options: [{ logical: 'parens' }], errors: [{ messageId: 'missingParens' }], @@ -1100,7 +1086,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ATTR_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: ATTR_PAREN_FRAGMENT, options: [{ prop: 'parens' }], errors: [{ messageId: 'missingParens' }], @@ -1119,7 +1105,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: RETURN_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(RETURN_PAREN_FRAGMENT), options: [{ return: 'parens-new-line' }], errors: [{ messageId: 'missingParens' }], @@ -1144,7 +1130,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: RETURN_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(RETURN_PAREN_FRAGMENT), options: [{ return: 'parens-new-line' }], errors: [{ messageId: 'parensOnNewLines' }], @@ -1160,7 +1146,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: DECLARATION_TERNARY_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(DECLARATION_TERNARY_PAREN_FRAGMENT), options: [{ declaration: 'parens-new-line' }], errors: [ @@ -1170,7 +1156,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: DECLARATION_TERNARY_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(DECLARATION_TERNARY_PAREN_FRAGMENT), options: [{ declaration: 'parens-new-line' }], errors: [ @@ -1189,7 +1175,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: DECLARATION_TERNARY_PAREN_FRAGMENT, - parser: parsers.TYPESCRIPT_ESLINT, + features: ['fragment'], output: addNewLineSymbols(DECLARATION_TERNARY_PAREN_FRAGMENT), options: [{ declaration: 'parens-new-line' }], errors: [ @@ -1208,7 +1194,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ASSIGNMENT_TERNARY_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(ASSIGNMENT_TERNARY_PAREN_FRAGMENT), options: [{ assignment: 'parens-new-line' }], errors: [ @@ -1227,7 +1213,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ASSIGNMENT_TERNARY_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(ASSIGNMENT_TERNARY_PAREN_FRAGMENT), options: [{ assignment: 'parens-new-line' }], errors: [ @@ -1267,7 +1253,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ARROW_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(ARROW_PAREN_FRAGMENT), options: [{ arrow: 'parens-new-line' }], errors: [{ messageId: 'parensOnNewLines' }], @@ -1280,7 +1266,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ARROW_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(ARROW_PAREN_FRAGMENT), options: [{ arrow: 'parens-new-line' }], errors: [{ messageId: 'missingParens' }], @@ -1293,7 +1279,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: CONDITION_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(CONDITION_PAREN_FRAGMENT), options: [{ condition: 'parens-new-line' }], errors: [{ messageId: 'parensOnNewLines' }], @@ -1306,7 +1292,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: CONDITION_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(CONDITION_PAREN_FRAGMENT), options: [{ condition: 'parens-new-line' }], errors: [{ messageId: 'missingParens' }], @@ -1325,7 +1311,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: LOGICAL_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: LOGICAL_PAREN_NEW_LINE_AUTOFIX_FRAGMENT, options: [{ logical: 'parens-new-line' }], errors: [{ messageId: 'missingParens' }], @@ -1338,7 +1324,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ATTR_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: addNewLineSymbols(ATTR_PAREN_FRAGMENT), options: [{ prop: 'parens-new-line' }], errors: [{ messageId: 'parensOnNewLines' }], @@ -1351,7 +1337,7 @@ ruleTester.run('jsx-wrap-multilines', rule, { }, { code: ATTR_NO_PAREN_FRAGMENT, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], output: ATTR_PAREN_NEW_LINE_AUTOFIX_FRAGMENT, options: [{ prop: 'parens-new-line' }], errors: [{ messageId: 'missingParens' }], @@ -1405,5 +1391,5 @@ ruleTester.run('jsx-wrap-multilines', rule, { options: [{ declaration: 'parens-new-line' }], errors: [{ messageId: 'missingParens' }], }, - ], + ]), }); diff --git a/tests/lib/rules/no-access-state-in-setstate.js b/tests/lib/rules/no-access-state-in-setstate.js index f183ce47b3..36a333fae6 100644 --- a/tests/lib/rules/no-access-state-in-setstate.js +++ b/tests/lib/rules/no-access-state-in-setstate.js @@ -32,7 +32,7 @@ const settings = { const ruleTester = new RuleTester({ settings }); ruleTester.run('no-access-state-in-setstate', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = React.createClass({ @@ -133,7 +133,7 @@ ruleTester.run('no-access-state-in-setstate', rule, { }; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -144,7 +144,7 @@ ruleTester.run('no-access-state-in-setstate', rule, { }; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, }, { @@ -157,9 +157,9 @@ ruleTester.run('no-access-state-in-setstate', rule, { `, parserOptions, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = React.createClass({ @@ -267,5 +267,5 @@ ruleTester.run('no-access-state-in-setstate', rule, { parserOptions, errors: [{ messageId: 'useCallback' }], }, - ], + ]), }); diff --git a/tests/lib/rules/no-adjacent-inline-elements.js b/tests/lib/rules/no-adjacent-inline-elements.js index a0bd9d573f..f2da87d7da 100644 --- a/tests/lib/rules/no-adjacent-inline-elements.js +++ b/tests/lib/rules/no-adjacent-inline-elements.js @@ -11,6 +11,7 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-adjacent-inline-elements'); +const parsers = require('../../helpers/parsers'); const parserOptions = { ecmaVersion: 6, @@ -26,7 +27,7 @@ const parserOptions = { const ruleTester = new RuleTester(); ruleTester.run('no-adjacent-inline-elements', rule, { - valid: [ + valid: parsers.all([ { code: '
;', parserOptions, @@ -46,6 +47,7 @@ ruleTester.run('no-adjacent-inline-elements', rule, { { code: '
 
;', parserOptions, + features: ['no-ts-old'], // TODO: FIXME: remove no-ts-old and fix }, { code: '
 some text  
;', @@ -72,8 +74,7 @@ ruleTester.run('no-adjacent-inline-elements', rule, { parserOptions, }, { - code: ('React.createElement("div", undefined, [React.createElement("a"), ' - + '" some text ", React.createElement("a")]);'), + code: ('React.createElement("div", undefined, [React.createElement("a"), " some text ", React.createElement("a")]);'), parserOptions, }, { @@ -84,8 +85,8 @@ ruleTester.run('no-adjacent-inline-elements', rule, { code: 'React.createElement(a, b);', parserOptions, }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: '
;', errors: [{ messageId: 'inlineElement' }], @@ -101,5 +102,5 @@ ruleTester.run('no-adjacent-inline-elements', rule, { errors: [{ messageId: 'inlineElement' }], parserOptions, }, - ], + ]), }); diff --git a/tests/lib/rules/no-array-index-key.js b/tests/lib/rules/no-array-index-key.js index b1e85fa15d..c6317a1ff4 100644 --- a/tests/lib/rules/no-array-index-key.js +++ b/tests/lib/rules/no-array-index-key.js @@ -27,7 +27,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-array-index-key', rule, { - valid: [].concat( + valid: parsers.all( { code: ';' }, { code: ';' }, { code: ';' }, @@ -92,29 +92,16 @@ ruleTester.run('no-array-index-key', rule, { }) `, }, - parsers.ES2020( - { - code: 'foo?.map(child => )', - parserOptions: { - ecmaVersion: 2020, - }, - }, - { - code: 'foo?.map(child => )', - parser: parsers.BABEL_ESLINT, - }, - { - code: 'foo?.map(child => )', - parser: parsers.TYPESCRIPT_ESLINT, + { + code: 'foo?.map(child => )', + features: ['optional chaining'], + parserOptions: { + ecmaVersion: 2020, }, - { - code: 'foo?.map(child => )', - parser: parsers['@TYPESCRIPT_ESLINT'], - } - ) + } ), - invalid: [].concat( + invalid: parsers.all([].concat( { code: 'foo.map((bar, i) => )', errors: [{ messageId: 'noArrayIndex' }], @@ -257,29 +244,13 @@ ruleTester.run('no-array-index-key', rule, { `, errors: [{ messageId: 'noArrayIndex' }], }, - parsers.ES2020( - { - code: 'foo?.map((child, i) => )', - errors: [{ messageId: 'noArrayIndex' }], - parserOptions: { - ecmaVersion: 2020, - }, - }, - { - code: 'foo?.map((child, i) => )', - errors: [{ messageId: 'noArrayIndex' }], - parser: parsers.BABEL_ESLINT, - }, - { - code: 'foo?.map((child, i) => )', - errors: [{ messageId: 'noArrayIndex' }], - parser: parsers.TYPESCRIPT_ESLINT, + { + code: 'foo?.map((child, i) => )', + errors: [{ messageId: 'noArrayIndex' }], + features: ['optional chaining'], + parserOptions: { + ecmaVersion: 2020, }, - { - code: 'foo?.map((child, i) => )', - errors: [{ messageId: 'noArrayIndex' }], - parser: parsers['@TYPESCRIPT_ESLINT'], - } - ) - ), + } + )), }); diff --git a/tests/lib/rules/no-arrow-function-lifecycle.js b/tests/lib/rules/no-arrow-function-lifecycle.js index 283e54b5d5..850d59d4ab 100644 --- a/tests/lib/rules/no-arrow-function-lifecycle.js +++ b/tests/lib/rules/no-arrow-function-lifecycle.js @@ -24,7 +24,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-arrow-function-lifecycle', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -167,7 +167,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -177,7 +177,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -187,7 +187,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -197,7 +197,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -207,7 +207,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -217,7 +217,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -227,7 +227,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -237,7 +237,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -247,7 +247,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -257,7 +257,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -267,7 +267,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -277,7 +277,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -287,7 +287,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -297,7 +297,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -307,7 +307,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -317,7 +317,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -327,7 +327,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -338,7 +338,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render() { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -348,20 +348,17 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { }); `, }, - ].concat( - parsers.TS([ - { - code: ` - class MyComponent extends React.Component { - onChange: () => void; - } - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - ]) - ), + { + code: ` + class MyComponent extends React.Component { + onChange: () => void; + } + `, + features: ['types'], + }, + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -607,7 +604,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [{ message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }], output: ` class Hello extends React.Component { @@ -624,7 +621,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'getDefaultProps is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -645,7 +642,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'getInitialState is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -666,7 +663,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'getChildContext is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -687,7 +684,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'getDerivedStateFromProps is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -708,7 +705,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'componentWillMount is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -729,7 +726,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'UNSAFE_componentWillMount is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -750,7 +747,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'componentDidMount is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -771,7 +768,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'componentWillReceiveProps is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -792,7 +789,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'UNSAFE_componentWillReceiveProps is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -813,7 +810,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'shouldComponentUpdate is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -834,7 +831,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'componentWillUpdate is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -855,7 +852,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'UNSAFE_componentWillUpdate is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -876,7 +873,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'getSnapshotBeforeUpdate is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -897,7 +894,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'componentDidUpdate is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -918,7 +915,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'componentDidCatch is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -939,7 +936,7 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { render = () => { return
; } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], errors: [ { message: 'componentWillUnmount is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, { message: 'render is a React lifecycle method, and should not be an arrow function or in a class field. Use an instance method instead.' }, @@ -952,5 +949,5 @@ ruleTester.run('no-arrow-function-lifecycle', rule, { } `, }, - ], + ]), }); diff --git a/tests/lib/rules/no-children-prop.js b/tests/lib/rules/no-children-prop.js index 4e80807417..93f0f4cf42 100644 --- a/tests/lib/rules/no-children-prop.js +++ b/tests/lib/rules/no-children-prop.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-children-prop'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-children-prop', rule, { - valid: [ + valid: parsers.all([ { code: '
;', }, @@ -170,8 +172,8 @@ ruleTester.run('no-children-prop', rule, { code: 'React.createElement(MyComponent, {children: function* () {}});', options: [{ allowFunctions: true }], }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: '
;', // not a valid use case but make sure we don't crash errors: [{ messageId: 'nestChildren' }], @@ -272,5 +274,5 @@ ruleTester.run('no-children-prop', rule, { options: [{ allowFunctions: true }], errors: [{ messageId: 'passFunctionAsArgs' }], }, - ], + ]), }); diff --git a/tests/lib/rules/no-danger-with-children.js b/tests/lib/rules/no-danger-with-children.js index 37a0a5ed31..b25397e0c6 100644 --- a/tests/lib/rules/no-danger-with-children.js +++ b/tests/lib/rules/no-danger-with-children.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-danger-with-children'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-danger-with-children', rule, { - valid: [ + valid: parsers.all([ { code: '
Children
', }, @@ -98,8 +100,8 @@ ruleTester.run('no-danger-with-children', rule, { const component = shallow(); `, }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: `
@@ -209,5 +211,5 @@ ruleTester.run('no-danger-with-children', rule, { `, errors: [{ messageId: 'dangerWithChildren' }], }, - ], + ]), }); diff --git a/tests/lib/rules/no-danger.js b/tests/lib/rules/no-danger.js index f08fca7743..a6f18630d5 100644 --- a/tests/lib/rules/no-danger.js +++ b/tests/lib/rules/no-danger.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-danger'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,12 +28,12 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-danger', rule, { - valid: [ + valid: parsers.all([ { code: ';' }, { code: ';' }, { code: '
;' }, - ], - invalid: [ + ]), + invalid: parsers.all([ { code: '
;', errors: [ @@ -41,5 +43,5 @@ ruleTester.run('no-danger', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/no-deprecated.js b/tests/lib/rules/no-deprecated.js index 68fa5dcf59..4c43bf18e2 100644 --- a/tests/lib/rules/no-deprecated.js +++ b/tests/lib/rules/no-deprecated.js @@ -44,7 +44,7 @@ function errorMessage(oldMethod, version, newMethod, refs, extraProps) { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-deprecated', rule, { - valid: [ + valid: parsers.all([ // Not deprecated 'var element = React.createElement(\'p\', {}, null);', 'var clone = React.cloneElement(element);', @@ -119,9 +119,9 @@ ruleTester.run('no-deprecated', rule, { let { default: defaultReactExport, ...allReactExports } = React; `, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: 'React.renderComponent()', errors: [errorMessage('React.renderComponent', '0.12.0', 'React.render')], @@ -182,12 +182,10 @@ ruleTester.run('no-deprecated', rule, { }, { code: 'var {createClass} = require(\'react\');', - parser: parsers.BABEL_ESLINT, errors: [errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')], }, { code: 'var {createClass, PropTypes} = require(\'react\');', - parser: parsers.BABEL_ESLINT, errors: [ errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class'), errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types'), @@ -195,12 +193,10 @@ ruleTester.run('no-deprecated', rule, { }, { code: 'import {createClass} from \'react\';', - parser: parsers.BABEL_ESLINT, errors: [errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')], }, { code: 'import {createClass, PropTypes} from \'react\';', - parser: parsers.BABEL_ESLINT, errors: [ errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class'), errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types'), @@ -211,7 +207,6 @@ ruleTester.run('no-deprecated', rule, { import React from 'react'; const {createClass, PropTypes} = React; `, - parser: parsers.BABEL_ESLINT, errors: [ errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class'), errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types'), @@ -219,7 +214,6 @@ ruleTester.run('no-deprecated', rule, { }, { code: 'import {printDOM} from \'react-addons-perf\';', - parser: parsers.BABEL_ESLINT, errors: [errorMessage('ReactPerf.printDOM', '15.0.0', 'ReactPerf.printOperations')], }, { @@ -227,7 +221,6 @@ ruleTester.run('no-deprecated', rule, { import ReactPerf from 'react-addons-perf'; const {printDOM} = ReactPerf; `, - parser: parsers.BABEL_ESLINT, errors: [errorMessage('ReactPerf.printDOM', '15.0.0', 'ReactPerf.printOperations')], }, { @@ -433,5 +426,5 @@ ruleTester.run('no-deprecated', rule, { ), ], }, - ], + ]), }); diff --git a/tests/lib/rules/no-did-mount-set-state.js b/tests/lib/rules/no-did-mount-set-state.js index 34465ea609..47dafb432e 100644 --- a/tests/lib/rules/no-did-mount-set-state.js +++ b/tests/lib/rules/no-did-mount-set-state.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-did-mount-set-state', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -81,11 +81,10 @@ ruleTester.run('no-did-mount-set-state', rule, { } }); `, - parser: parsers.BABEL_ESLINT, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -113,7 +112,6 @@ ruleTester.run('no-did-mount-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'noSetState', @@ -131,7 +129,7 @@ ruleTester.run('no-did-mount-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix errors: [ { messageId: 'noSetState', @@ -167,7 +165,6 @@ ruleTester.run('no-did-mount-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, options: ['disallow-in-func'], errors: [ { @@ -208,7 +205,6 @@ ruleTester.run('no-did-mount-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, options: ['disallow-in-func'], errors: [ { @@ -248,7 +244,6 @@ ruleTester.run('no-did-mount-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'noSetState', @@ -264,7 +259,6 @@ ruleTester.run('no-did-mount-set-state', rule, { } }); `, - parser: parsers.BABEL_ESLINT, options: ['disallow-in-func'], errors: [ { @@ -281,7 +275,6 @@ ruleTester.run('no-did-mount-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, options: ['disallow-in-func'], errors: [ { @@ -290,5 +283,5 @@ ruleTester.run('no-did-mount-set-state', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/no-did-update-set-state.js b/tests/lib/rules/no-did-update-set-state.js index a6d81fb023..a3cde7bfc8 100644 --- a/tests/lib/rules/no-did-update-set-state.js +++ b/tests/lib/rules/no-did-update-set-state.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-did-update-set-state', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -81,11 +81,10 @@ ruleTester.run('no-did-update-set-state', rule, { } }); `, - parser: parsers.BABEL_ESLINT, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -113,7 +112,6 @@ ruleTester.run('no-did-update-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'noSetState', @@ -131,7 +129,8 @@ ruleTester.run('no-did-update-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove no-ts-old and fix + errors: [ { messageId: 'noSetState', @@ -167,7 +166,6 @@ ruleTester.run('no-did-update-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, options: ['disallow-in-func'], errors: [ { @@ -208,7 +206,6 @@ ruleTester.run('no-did-update-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, options: ['disallow-in-func'], errors: [ { @@ -248,7 +245,6 @@ ruleTester.run('no-did-update-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'noSetState', @@ -264,7 +260,6 @@ ruleTester.run('no-did-update-set-state', rule, { } }); `, - parser: parsers.BABEL_ESLINT, options: ['disallow-in-func'], errors: [ { @@ -281,7 +276,6 @@ ruleTester.run('no-did-update-set-state', rule, { } } `, - parser: parsers.BABEL_ESLINT, options: ['disallow-in-func'], errors: [ { @@ -290,5 +284,5 @@ ruleTester.run('no-did-update-set-state', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/no-direct-mutation-state.js b/tests/lib/rules/no-direct-mutation-state.js index 6dd39a2880..fa9f731188 100644 --- a/tests/lib/rules/no-direct-mutation-state.js +++ b/tests/lib/rules/no-direct-mutation-state.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-direct-mutation-state'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-direct-mutation-state', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -96,9 +98,9 @@ ruleTester.run('no-direct-mutation-state', rule, { } `, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -262,19 +264,19 @@ ruleTester.run('no-direct-mutation-state', rule, { `, errors: [{ messageId: 'noDirectMutation' }], }, - /** - * Would be nice to prevent this too - , { - code: ` - var Hello = createReactClass({ - render: function() { - var that = this; - that.state.person.name.first = "bar" - return
Hello
; - } - }); - `, - errors: [{messageId: 'noDirectMutation'}] - } */ - ], + /** + * Would be nice to prevent this too + { + code: ` + var Hello = createReactClass({ + render: function() { + var that = this; + that.state.person.name.first = "bar" + return
Hello
; + } + }); + `, + errors: [{messageId: 'noDirectMutation'}] + } */ + ]), }); diff --git a/tests/lib/rules/no-find-dom-node.js b/tests/lib/rules/no-find-dom-node.js index 2cb2d3f93f..4d6890a2e1 100644 --- a/tests/lib/rules/no-find-dom-node.js +++ b/tests/lib/rules/no-find-dom-node.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-find-dom-node'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-find-dom-node', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = function() {}; @@ -66,9 +68,9 @@ ruleTester.run('no-find-dom-node', rule, { }); `, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -121,5 +123,5 @@ ruleTester.run('no-find-dom-node', rule, { `, errors: [{ messageId: 'noFindDOMNode' }], }, - ], + ]), }); diff --git a/tests/lib/rules/no-is-mounted.js b/tests/lib/rules/no-is-mounted.js index 9316b54aca..9fb5b7d31d 100644 --- a/tests/lib/rules/no-is-mounted.js +++ b/tests/lib/rules/no-is-mounted.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-is-mounted'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-is-mounted', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = function() { @@ -55,9 +57,9 @@ ruleTester.run('no-is-mounted', rule, { }); `, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -103,5 +105,5 @@ ruleTester.run('no-is-mounted', rule, { `, errors: [{ messageId: 'noIsMounted' }], }, - ], + ]), }); diff --git a/tests/lib/rules/no-multi-comp.js b/tests/lib/rules/no-multi-comp.js index 7422f94cd1..36ae89d28a 100644 --- a/tests/lib/rules/no-multi-comp.js +++ b/tests/lib/rules/no-multi-comp.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-multi-comp', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = require('./components/Hello'); @@ -72,7 +72,6 @@ ruleTester.run('no-multi-comp', rule, { return
Hello again {props.name}
; } `, - parser: parsers.BABEL_ESLINT, options: [{ ignoreStateless: true }], }, { @@ -202,11 +201,11 @@ ruleTester.run('no-multi-comp', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -265,7 +264,6 @@ ruleTester.run('no-multi-comp', rule, { return
Hello again {props.name}
; } `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'onlyOneComponent', @@ -304,7 +302,6 @@ ruleTester.run('no-multi-comp', rule, { } }; `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'onlyOneComponent', @@ -324,7 +321,7 @@ ruleTester.run('no-multi-comp', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], errors: [ { messageId: 'onlyOneComponent', @@ -340,7 +337,6 @@ ruleTester.run('no-multi-comp', rule, { export default React.forwardRef((props, ref) =>
); `, options: [{ ignoreStateless: false }], - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'onlyOneComponent', @@ -356,7 +352,6 @@ ruleTester.run('no-multi-comp', rule, { const HelloComponent2 = React.forwardRef((props, ref) =>
); `, options: [{ ignoreStateless: false }], - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'onlyOneComponent', @@ -372,7 +367,7 @@ ruleTester.run('no-multi-comp', rule, { const HelloComponent2 = React.forwardRef((props, ref) => <>); `, options: [{ ignoreStateless: false }], - parser: parsers.BABEL_ESLINT, + features: ['fragment'], errors: [ { messageId: 'onlyOneComponent', @@ -555,5 +550,5 @@ ruleTester.run('no-multi-comp', rule, { }, errors: [{ messageId: 'onlyOneComponent' }], }, - ], + ]), }); diff --git a/tests/lib/rules/no-namespace.js b/tests/lib/rules/no-namespace.js index eaf9555738..1056e99d74 100644 --- a/tests/lib/rules/no-namespace.js +++ b/tests/lib/rules/no-namespace.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-namespace'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-namespace', rule, { - valid: [ + valid: parsers.all([ { code: '', }, @@ -108,72 +110,88 @@ ruleTester.run('no-namespace', rule, { { code: 'React.createElement({})', }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: '', errors: [{ message: 'React component ns:testcomponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: 'React.createElement("ns:testcomponent")', errors: [{ message: 'React component ns:testcomponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: '', errors: [{ message: 'React component ns:testComponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: 'React.createElement("ns:testComponent")', errors: [{ message: 'React component ns:testComponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: '', errors: [{ message: 'React component ns:test_component must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: 'React.createElement("ns:test_component")', errors: [{ message: 'React component ns:test_component must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: '', errors: [{ message: 'React component ns:TestComponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: 'React.createElement("ns:TestComponent")', errors: [{ message: 'React component ns:TestComponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: '', errors: [{ message: 'React component Ns:testcomponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: 'React.createElement("Ns:testcomponent")', errors: [{ message: 'React component Ns:testcomponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: '', errors: [{ message: 'React component Ns:testComponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: 'React.createElement("Ns:testComponent")', errors: [{ message: 'React component Ns:testComponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: '', errors: [{ message: 'React component Ns:test_component must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: 'React.createElement("Ns:test_component")', errors: [{ message: 'React component Ns:test_component must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: '', errors: [{ message: 'React component Ns:TestComponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, { code: 'React.createElement("Ns:TestComponent")', errors: [{ message: 'React component Ns:TestComponent must not be in a namespace, as React does not support them' }], + features: ['jsx namespace'], }, - ], + ]), }); diff --git a/tests/lib/rules/no-redundant-should-component-update.js b/tests/lib/rules/no-redundant-should-component-update.js index 4138de002d..88e5a3e519 100644 --- a/tests/lib/rules/no-redundant-should-component-update.js +++ b/tests/lib/rules/no-redundant-should-component-update.js @@ -26,7 +26,7 @@ const parserOptions = { const ruleTester = new RuleTester(); ruleTester.run('no-redundant-should-component-update', rule, { - valid: [ + valid: parsers.all([ { code: ` class Foo extends React.Component { @@ -46,7 +46,6 @@ ruleTester.run('no-redundant-should-component-update', rule, { } `, parserOptions, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -56,7 +55,7 @@ ruleTester.run('no-redundant-should-component-update', rule, { } } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, }, { @@ -71,9 +70,9 @@ ruleTester.run('no-redundant-should-component-update', rule, { `, parserOptions, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` class Foo extends React.PureComponent { @@ -120,7 +119,7 @@ ruleTester.run('no-redundant-should-component-update', rule, { data: { component: 'Foo' }, }, ], - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, }, { @@ -175,5 +174,5 @@ ruleTester.run('no-redundant-should-component-update', rule, { ], parserOptions, }, - ], + ]), }); diff --git a/tests/lib/rules/no-render-return-value.js b/tests/lib/rules/no-render-return-value.js index bbf7474a80..18caa88b5c 100644 --- a/tests/lib/rules/no-render-return-value.js +++ b/tests/lib/rules/no-render-return-value.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-render-return-value'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-render-return-value', rule, { - valid: [ + valid: parsers.all([ { code: 'ReactDOM.render(
, document.body);', }, @@ -58,9 +60,9 @@ ruleTester.run('no-render-return-value', rule, { { code: 'var foo = ReactDom.renderder(
, root)', }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: 'var Hello = ReactDOM.render(
, document.body);', errors: [ @@ -153,5 +155,5 @@ ruleTester.run('no-render-return-value', rule, { }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/no-set-state.js b/tests/lib/rules/no-set-state.js index 47c5d6e9c3..3060c8e1d1 100644 --- a/tests/lib/rules/no-set-state.js +++ b/tests/lib/rules/no-set-state.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-set-state', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = function() { @@ -58,9 +58,9 @@ ruleTester.run('no-set-state', rule, { }); `, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -119,7 +119,7 @@ ruleTester.run('no-set-state', rule, { } }; `, - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove `no-ts-old` and fix errors: [{ messageId: 'noSetState' }], }, { @@ -130,8 +130,7 @@ ruleTester.run('no-set-state', rule, { } }; `, - parser: parsers.BABEL_ESLINT, errors: [{ messageId: 'noSetState' }], }, - ], + ]), }); diff --git a/tests/lib/rules/no-string-refs.js b/tests/lib/rules/no-string-refs.js index 1ceb8c7870..fba476860d 100644 --- a/tests/lib/rules/no-string-refs.js +++ b/tests/lib/rules/no-string-refs.js @@ -28,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-refs', rule, { - valid: [ + valid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -40,7 +40,6 @@ ruleTester.run('no-refs', rule, { } }); `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -50,7 +49,6 @@ ruleTester.run('no-refs', rule, { } }); `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -60,11 +58,10 @@ ruleTester.run('no-refs', rule, { } }); `, - parser: parsers.BABEL_ESLINT, }, - ], + ]), - invalid: [ + invalid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -76,7 +73,6 @@ ruleTester.run('no-refs', rule, { } }); `, - parser: parsers.BABEL_ESLINT, errors: [{ messageId: 'thisRefsDeprecated' }], }, { @@ -87,7 +83,6 @@ ruleTester.run('no-refs', rule, { } }); `, - parser: parsers.BABEL_ESLINT, errors: [{ messageId: 'stringInRefDeprecated' }], }, { @@ -98,7 +93,6 @@ ruleTester.run('no-refs', rule, { } }); `, - parser: parsers.BABEL_ESLINT, errors: [{ messageId: 'stringInRefDeprecated' }], }, { @@ -112,7 +106,6 @@ ruleTester.run('no-refs', rule, { } }); `, - parser: parsers.BABEL_ESLINT, errors: [ { messageId: 'thisRefsDeprecated' }, { messageId: 'stringInRefDeprecated' }, @@ -129,7 +122,6 @@ ruleTester.run('no-refs', rule, { } }); `, - parser: parsers.BABEL_ESLINT, options: [{ noTemplateLiterals: true }], errors: [ { messageId: 'thisRefsDeprecated' }, @@ -147,12 +139,11 @@ ruleTester.run('no-refs', rule, { } }); `, - parser: parsers.BABEL_ESLINT, options: [{ noTemplateLiterals: true }], errors: [ { messageId: 'thisRefsDeprecated' }, { messageId: 'stringInRefDeprecated' }, ], }, - ], + ]), }); diff --git a/tests/lib/rules/no-this-in-sfc.js b/tests/lib/rules/no-this-in-sfc.js index a0836d48e5..a8e80b8b45 100644 --- a/tests/lib/rules/no-this-in-sfc.js +++ b/tests/lib/rules/no-this-in-sfc.js @@ -23,7 +23,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-this-in-sfc', rule, { - valid: [].concat( + valid: parsers.all([ { code: ` function Foo(props) { @@ -139,7 +139,7 @@ ruleTester.run('no-this-in-sfc', rule, { }; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], }, { code: ` @@ -152,7 +152,6 @@ ruleTester.run('no-this-in-sfc', rule, { }; }; `, - parser: parsers.BABEL_ESLINT, }, { code: ` @@ -176,21 +175,20 @@ ruleTester.run('no-this-in-sfc', rule, { return this.a || null; }; `, - }, parsers.TS([ - { - code: ` - $.fn.getValueAsStringWeak = function (): string | null { - const val = this.length === 1 ? this.val() : null; - - return typeof val === 'string' ? val : null; - }; - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - }, - ]) - ), + }, + { + code: ` + $.fn.getValueAsStringWeak = function (): string | null { + const val = this.length === 1 ? this.val() : null; + + return typeof val === 'string' ? val : null; + }; + `, + features: ['types'], + }, + ]), - invalid: [ + invalid: parsers.all([ { code: ` function Foo(props) { @@ -299,7 +297,7 @@ ruleTester.run('no-this-in-sfc', rule, { }; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields', 'no-ts-old'], // TODO: FIXME: remove `no-ts-old` and fix errors: [{ messageId: 'noThisInSFC' }], }, { @@ -330,5 +328,5 @@ ruleTester.run('no-this-in-sfc', rule, { `, errors: [{ messageId: 'noThisInSFC' }], }, - ], + ]), }); diff --git a/tests/lib/rules/no-typos.js b/tests/lib/rules/no-typos.js index 9837ace9e8..44dfbecf7b 100644 --- a/tests/lib/rules/no-typos.js +++ b/tests/lib/rules/no-typos.js @@ -31,7 +31,7 @@ const parserOptions = { const ruleTester = new RuleTester(); ruleTester.run('no-typos', rule, { - valid: [].concat( + valid: parsers.all([].concat( { code: ` import createReactClass from 'create-react-class' @@ -45,8 +45,8 @@ ruleTester.run('no-typos', rule, { }) } `, - parser: parsers.TYPESCRIPT_ESLINT, parserOptions, + features: ['no-babel'], // TODO: FIXME: remove no-babel and fix crash }, { code: ` @@ -57,7 +57,7 @@ ruleTester.run('no-typos', rule, { static DefaultProps = {key: "myValue"}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, }, { @@ -79,7 +79,7 @@ ruleTester.run('no-typos', rule, { static defaultProps = {key: "myValue"}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, }, { @@ -101,7 +101,7 @@ ruleTester.run('no-typos', rule, { defaultProps = {key: "myValue"}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, }, { @@ -113,7 +113,7 @@ ruleTester.run('no-typos', rule, { DefaultProps = {key: "myValue"}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, }, { @@ -125,7 +125,7 @@ ruleTester.run('no-typos', rule, { defaultprops = {key: "myValue"}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, }, { @@ -137,7 +137,6 @@ ruleTester.run('no-typos', rule, { static DefaultProps() {}; } `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -149,7 +148,6 @@ ruleTester.run('no-typos', rule, { static defaultprops() {}; } `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -299,7 +297,6 @@ ruleTester.run('no-typos', rule, { } function a() {} `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -310,7 +307,6 @@ ruleTester.run('no-typos', rule, { a: PropTypes.number.isRequired } `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -323,7 +319,6 @@ ruleTester.run('no-typos', rule, { }) } `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -339,7 +334,6 @@ ruleTester.run('no-typos', rule, { }).isRequired } `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -353,7 +347,6 @@ ruleTester.run('no-typos', rule, { ]) } `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -367,23 +360,6 @@ ruleTester.run('no-typos', rule, { ]) } `, - parser: parsers.BABEL_ESLINT, - parserOptions, - }, - { - code: ` - import PropTypes from "prop-types"; - class Component extends React.Component {}; - Component.childContextTypes = { - a: PropTypes.string, - b: PropTypes.string.isRequired, - c: PropTypes.shape({ - d: PropTypes.string, - e: PropTypes.number.isRequired, - }).isRequired - } - `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -451,73 +427,6 @@ ruleTester.run('no-typos', rule, { `, parserOptions, }, - { - code: ` - import PropTypes from "prop-types"; - class Component extends React.Component {}; - Component.contextTypes = { - a: PropTypes.string, - b: PropTypes.string.isRequired, - c: PropTypes.shape({ - d: PropTypes.string, - e: PropTypes.number.isRequired, - }).isRequired - } - `, - parser: parsers.BABEL_ESLINT, - parserOptions, - }, - { - code: ` - import PropTypes from 'prop-types' - import * as MyPropTypes from 'lib/my-prop-types' - class Component extends React.Component {}; - Component.propTypes = { - a: PropTypes.string, - b: MyPropTypes.MYSTRING, - c: MyPropTypes.MYSTRING.isRequired, - } - `, - parser: parsers.BABEL_ESLINT, - parserOptions, - }, - { - code: ` - import PropTypes from "prop-types" - import * as MyPropTypes from 'lib/my-prop-types' - class Component extends React.Component {}; - Component.propTypes = { - b: PropTypes.string, - a: MyPropTypes.MYSTRING, - } - `, - parser: parsers.BABEL_ESLINT, - parserOptions, - }, - { - code: ` - import CustomReact from "react" - class Component extends React.Component {}; - Component.propTypes = { - b: CustomReact.PropTypes.string, - } - `, - parser: parsers.BABEL_ESLINT, - parserOptions, - }, - { - // ensure that an absent arg to PropTypes.shape does not crash - code: ` - class Component extends React.Component {}; - Component.propTypes = { - a: PropTypes.shape(), - }; - Component.contextTypes = { - a: PropTypes.shape(), - }; - `, - parserOptions, - }, { // ensure that an absent arg to PropTypes.shape does not crash code: ` @@ -529,7 +438,6 @@ ruleTester.run('no-typos', rule, { a: PropTypes.shape(), }; `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -539,18 +447,6 @@ ruleTester.run('no-typos', rule, { data.time = data.time || {}; }; `, - parser: parsers.BABEL_ESLINT, - }, - { - code: ` - class Component extends React.Component {}; - Component.propTypes = { - b: string.isRequired, - c: PropTypes.shape({ - d: number.isRequired, - }).isRequired - } - `, parserOptions, }, { @@ -563,22 +459,6 @@ ruleTester.run('no-typos', rule, { }).isRequired } `, - parser: parsers.BABEL_ESLINT, - parserOptions, - }, - { - code: ` - import React from 'react'; - import PropTypes from 'prop-types'; - const Component = React.createReactClass({ - propTypes: { - a: PropTypes.string.isRequired, - b: PropTypes.shape({ - c: PropTypes.number - }).isRequired - } - }); - `, parserOptions, }, { @@ -594,22 +474,6 @@ ruleTester.run('no-typos', rule, { } }); `, - parser: parsers.BABEL_ESLINT, - parserOptions, - }, - { - code: ` - import React from 'react'; - import PropTypes from 'prop-types'; - const Component = React.createReactClass({ - childContextTypes: { - a: PropTypes.bool, - b: PropTypes.array, - c: PropTypes.func, - d: PropTypes.object, - } - }); - `, parserOptions, }, { @@ -625,28 +489,6 @@ ruleTester.run('no-typos', rule, { } }); `, - parser: parsers.BABEL_ESLINT, - parserOptions, - }, - { - code: ` - import React from 'react'; - const Component = React.createReactClass({ - propTypes: {}, - childContextTypes: {}, - contextTypes: {}, - componentWillMount() { }, - componentDidMount() { }, - componentWillReceiveProps() { }, - shouldComponentUpdate() { }, - componentWillUpdate() { }, - componentDidUpdate() { }, - componentWillUnmount() { }, - render() { - return
Hello {this.props.name}
; - } - }); - `, parserOptions, }, { @@ -668,7 +510,6 @@ ruleTester.run('no-typos', rule, { } }); `, - parser: parsers.BABEL_ESLINT, parserOptions, }, { @@ -742,16 +583,16 @@ ruleTester.run('no-typos', rule, { shippedProposals: true, }, } : [] - ), + )), - invalid: [].concat( + invalid: parsers.all([].concat( { code: ` class Component extends React.Component { static PropTypes = {}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [ { messageId: 'typoStaticClassProp', type: 'Identifier' }, @@ -783,7 +624,7 @@ ruleTester.run('no-typos', rule, { static proptypes = {}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [{ messageId: 'typoStaticClassProp' }], }, @@ -809,7 +650,7 @@ ruleTester.run('no-typos', rule, { static ContextTypes = {}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [ { messageId: 'typoStaticClassProp', type: 'Identifier' }, @@ -837,7 +678,7 @@ ruleTester.run('no-typos', rule, { static contexttypes = {}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [{ messageId: 'typoStaticClassProp' }], }, @@ -863,7 +704,7 @@ ruleTester.run('no-typos', rule, { static ChildContextTypes = {}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [{ messageId: 'typoStaticClassProp' }], }, @@ -889,7 +730,7 @@ ruleTester.run('no-typos', rule, { static childcontexttypes = {}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [{ messageId: 'typoStaticClassProp' }], }, @@ -915,7 +756,7 @@ ruleTester.run('no-typos', rule, { static DefaultProps = {}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [ { messageId: 'typoStaticClassProp', type: 'Identifier' }, @@ -947,7 +788,7 @@ ruleTester.run('no-typos', rule, { static defaultprops = {}; } `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [{ messageId: 'typoStaticClassProp' }], }, @@ -1420,7 +1261,7 @@ ruleTester.run('no-typos', rule, { } }; `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [ { @@ -1438,7 +1279,7 @@ ruleTester.run('no-typos', rule, { } }; `, - parser: parsers.BABEL_ESLINT, + features: ['class fields'], parserOptions, errors: [ { @@ -1455,7 +1296,6 @@ ruleTester.run('no-typos', rule, { a: PropTypes.Number } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1475,7 +1315,6 @@ ruleTester.run('no-typos', rule, { }) } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1495,7 +1334,6 @@ ruleTester.run('no-typos', rule, { ]) } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1515,7 +1353,6 @@ ruleTester.run('no-typos', rule, { d: PropTypes.objectof, } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1547,7 +1384,6 @@ ruleTester.run('no-typos', rule, { d: PropTypes.objectof, } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1579,7 +1415,6 @@ ruleTester.run('no-typos', rule, { d: PropTypes.objectof, } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1623,30 +1458,6 @@ ruleTester.run('no-typos', rule, { }, ], }, - { - code: ` - import PropTypes from 'prop-types'; - class Component extends React.Component {}; - Component.propTypes = { - a: PropTypes.string.isrequired, - b: PropTypes.shape({ - c: PropTypes.number - }).isrequired - } - `, - parser: parsers.BABEL_ESLINT, - parserOptions, - errors: [ - { - messageId: 'typoPropTypeChain', - data: { name: 'isrequired' }, - }, - { - messageId: 'typoPropTypeChain', - data: { name: 'isrequired' }, - }, - ], - }, { code: ` import RealPropTypes from 'prop-types'; @@ -1658,7 +1469,6 @@ ruleTester.run('no-typos', rule, { d: RealPropTypes.objectof, } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1690,7 +1500,6 @@ ruleTester.run('no-typos', rule, { }).isrequired } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1714,7 +1523,6 @@ ruleTester.run('no-typos', rule, { d: React.PropTypes.objectof, } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1746,7 +1554,6 @@ ruleTester.run('no-typos', rule, { }).isrequired } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1764,7 +1571,6 @@ ruleTester.run('no-typos', rule, { import 'react'; class Component extends React.Component {}; `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1783,38 +1589,6 @@ ruleTester.run('no-typos', rule, { d: PropTypes.objectof, } `, - parser: parsers.BABEL_ESLINT, - parserOptions, - errors: [ - { - messageId: 'typoPropType', - data: { name: 'bools' }, - }, - { - messageId: 'typoPropType', - data: { name: 'Array' }, - }, - { - messageId: 'typoPropType', - data: { name: 'function' }, - }, - { - messageId: 'typoPropType', - data: { name: 'objectof' }, - }, - ], - }, - { - code: ` - import PropTypes from 'prop-types'; - class Component extends React.Component {}; - Component.childContextTypes = { - a: PropTypes.bools, - b: PropTypes.Array, - c: PropTypes.function, - d: PropTypes.objectof, - } - `, parserOptions, errors: [ { @@ -1846,7 +1620,6 @@ ruleTester.run('no-typos', rule, { }).isrequired } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -1882,205 +1655,6 @@ ruleTester.run('no-typos', rule, { }, ], }, - { - code: ` - import RealPropTypes from 'prop-types'; - class Component extends React.Component {}; - Component.childContextTypes = { - a: RealPropTypes.bools, - b: RealPropTypes.Array, - c: RealPropTypes.function, - d: RealPropTypes.objectof, - } - `, - parserOptions, - errors: [ - { - messageId: 'typoPropType', - data: { name: 'bools' }, - }, - { - messageId: 'typoPropType', - data: { name: 'Array' }, - }, - { - messageId: 'typoPropType', - data: { name: 'function' }, - }, - { - messageId: 'typoPropType', - data: { name: 'objectof' }, - }, - ], - }, - { - code: ` - import React from 'react'; - class Component extends React.Component {}; - Component.propTypes = { - a: React.PropTypes.string.isrequired, - b: React.PropTypes.shape({ - c: React.PropTypes.number - }).isrequired - } - `, - parserOptions, - errors: [ - { - messageId: 'typoPropTypeChain', - data: { name: 'isrequired' }, - }, - { - messageId: 'typoPropTypeChain', - data: { name: 'isrequired' }, - }, - ], - }, - { - code: ` - import React from 'react'; - class Component extends React.Component {}; - Component.childContextTypes = { - a: React.PropTypes.bools, - b: React.PropTypes.Array, - c: React.PropTypes.function, - d: React.PropTypes.objectof, - } - `, - parserOptions, - errors: [ - { - messageId: 'typoPropType', - data: { name: 'bools' }, - }, - { - messageId: 'typoPropType', - data: { name: 'Array' }, - }, - { - messageId: 'typoPropType', - data: { name: 'function' }, - }, - { - messageId: 'typoPropType', - data: { name: 'objectof' }, - }, - ], - }, - { - code: ` - import { PropTypes } from 'react'; - class Component extends React.Component {}; - Component.propTypes = { - a: PropTypes.string.isrequired, - b: PropTypes.shape({ - c: PropTypes.number - }).isrequired - } - `, - parserOptions, - errors: [ - { - messageId: 'typoPropTypeChain', - data: { name: 'isrequired' }, - }, - { - messageId: 'typoPropTypeChain', - data: { name: 'isrequired' }, - }, - ], - }, - { - code: ` - import { PropTypes } from 'react'; - class Component extends React.Component {}; - Component.childContextTypes = { - a: PropTypes.bools, - b: PropTypes.Array, - c: PropTypes.function, - d: PropTypes.objectof, - } - `, - parserOptions, - errors: [ - { - messageId: 'typoPropType', - data: { name: 'bools' }, - }, - { - messageId: 'typoPropType', - data: { name: 'Array' }, - }, - { - messageId: 'typoPropType', - data: { name: 'function' }, - }, - { - messageId: 'typoPropType', - data: { name: 'objectof' }, - }, - ], - }, - { - code: ` - import React from 'react'; - import PropTypes from 'prop-types'; - const Component = React.createReactClass({ - propTypes: { - a: PropTypes.string.isrequired, - b: PropTypes.shape({ - c: PropTypes.number - }).isrequired - } - }); - `, - parser: parsers.BABEL_ESLINT, - parserOptions, - errors: [ - { - messageId: 'typoPropTypeChain', - data: { name: 'isrequired' }, - }, - { - messageId: 'typoPropTypeChain', - data: { name: 'isrequired' }, - }, - ], - }, - { - code: ` - import React from 'react'; - import PropTypes from 'prop-types'; - const Component = React.createReactClass({ - childContextTypes: { - a: PropTypes.bools, - b: PropTypes.Array, - c: PropTypes.function, - d: PropTypes.objectof, - } - }); - `, - parser: parsers.BABEL_ESLINT, - parserOptions, - errors: [ - { - messageId: 'typoPropType', - data: { name: 'bools' }, - }, - { - messageId: 'typoPropType', - data: { name: 'Array' }, - }, - { - messageId: 'typoPropType', - data: { name: 'function' }, - }, - { - messageId: 'typoPropType', - data: { name: 'objectof' }, - }, - ], - }, { code: ` import React from 'react'; @@ -2263,7 +1837,6 @@ ruleTester.run('no-typos', rule, { getDerivedStateFromProps() { } } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -2279,7 +1852,6 @@ ruleTester.run('no-typos', rule, { GetDerivedStateFromProps() { } } `, - parser: parsers.BABEL_ESLINT, parserOptions, errors: [ { @@ -2297,125 +1869,6 @@ ruleTester.run('no-typos', rule, { }, ], }, - { - code: ` - import React from 'react'; - const Component = React.createReactClass({ - proptypes: {}, - childcontexttypes: {}, - contexttypes: {}, - getdefaultProps() { }, - getinitialState() { }, - getChildcontext() { }, - ComponentWillMount() { }, - ComponentDidMount() { }, - ComponentWillReceiveProps() { }, - ShouldComponentUpdate() { }, - ComponentWillUpdate() { }, - ComponentDidUpdate() { }, - ComponentWillUnmount() { }, - render() { - return
Hello {this.props.name}
; - } - }); - `, - parser: parsers.BABEL_ESLINT, - parserOptions, - errors: [ - { - messageId: 'typoPropDeclaration', - type: 'Identifier', - }, - { - messageId: 'typoPropDeclaration', - type: 'Identifier', - }, - { - messageId: 'typoPropDeclaration', - type: 'Identifier', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'getdefaultProps', - expected: 'getDefaultProps', - }, - type: 'Property', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'getinitialState', - expected: 'getInitialState', - }, - type: 'Property', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'getChildcontext', - expected: 'getChildContext', - }, - type: 'Property', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'ComponentWillMount', - expected: 'componentWillMount', - }, - type: 'Property', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'ComponentDidMount', - expected: 'componentDidMount', - }, - type: 'Property', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'ComponentWillReceiveProps', - expected: 'componentWillReceiveProps', - }, - type: 'Property', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'ShouldComponentUpdate', - expected: 'shouldComponentUpdate', - }, - type: 'Property', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'ComponentWillUpdate', - expected: 'componentWillUpdate', - }, - type: 'Property', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'ComponentDidUpdate', - expected: 'componentDidUpdate', - }, - type: 'Property', - }, - { - messageId: 'typoLifecycleMethod', - data: { - actual: 'ComponentWillUnmount', - expected: 'componentWillUnmount', - }, - type: 'Property', - }, - ], - }, semver.satisfies(version, '^5') ? { // PropTypes declared on a component that is detected through JSDoc comments and is // declared AFTER the PropTypes assignment @@ -2432,23 +1885,12 @@ ruleTester.run('no-typos', rule, { }, ], } : [], - parsers.TS([ - { - code: ` - import 'prop-types' - `, - parser: parsers.TYPESCRIPT_ESLINT, - parserOptions, - errors: [{ messageId: 'noPropTypesBinding' }], - }, - { - code: ` - import 'prop-types' - `, - parser: parsers['@TYPESCRIPT_ESLINT'], - parserOptions, - errors: [{ messageId: 'noPropTypesBinding' }], - }, - ]) - ), + { + code: ` + import 'prop-types' + `, + parserOptions, + errors: [{ messageId: 'noPropTypesBinding' }], + } + )), }); diff --git a/tests/lib/rules/no-unescaped-entities.js b/tests/lib/rules/no-unescaped-entities.js index d508862b43..097041e9b1 100644 --- a/tests/lib/rules/no-unescaped-entities.js +++ b/tests/lib/rules/no-unescaped-entities.js @@ -38,7 +38,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-unescaped-entities', rule, { - valid: [].concat( + valid: parsers.all([ { code: ` var Hello = createReactClass({ @@ -96,7 +96,7 @@ ruleTester.run('no-unescaped-entities', rule, { } }); `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -106,7 +106,7 @@ ruleTester.run('no-unescaped-entities', rule, { } }); `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], }, { code: ` @@ -116,11 +116,11 @@ ruleTester.run('no-unescaped-entities', rule, { }, }); `, - parser: parsers.BABEL_ESLINT, - } - ), + features: ['fragment'], + }, + ]), - invalid: [].concat( + invalid: parsers.all([].concat( allowsInvalidJSX ? [ { code: ` @@ -201,7 +201,7 @@ ruleTester.run('no-unescaped-entities', rule, { } }); `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts', 'no-default'], errors: [ { messageId: 'unescapedEntityAlts', @@ -219,7 +219,7 @@ ruleTester.run('no-unescaped-entities', rule, { } }); `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts', 'no-default'], errors: [ { messageId: 'unescapedEntityAlts', @@ -250,7 +250,7 @@ ruleTester.run('no-unescaped-entities', rule, { } }); `, - parser: parsers.BABEL_ESLINT, + features: ['fragment', 'no-ts', 'no-default'], errors: [ { messageId: 'unescapedEntityAlts', @@ -266,7 +266,7 @@ ruleTester.run('no-unescaped-entities', rule, { } }); `, - parser: parsers.BABEL_ESLINT, + features: ['fragment'], errors: [ { messageId: 'unescapedEntity', @@ -316,5 +316,5 @@ ruleTester.run('no-unescaped-entities', rule, { }, ], } - ).filter(Boolean), + )), }); diff --git a/tests/lib/rules/no-unknown-property.js b/tests/lib/rules/no-unknown-property.js index 77b6195266..c273ac7b2e 100644 --- a/tests/lib/rules/no-unknown-property.js +++ b/tests/lib/rules/no-unknown-property.js @@ -12,6 +12,8 @@ const RuleTester = require('eslint').RuleTester; const rule = require('../../../lib/rules/no-unknown-property'); +const parsers = require('../../helpers/parsers'); + const parserOptions = { ecmaVersion: 2018, sourceType: 'module', @@ -26,7 +28,7 @@ const parserOptions = { const ruleTester = new RuleTester({ parserOptions }); ruleTester.run('no-unknown-property', rule, { - valid: [ + valid: parsers.all([ { code: ';' }, { code: ';' }, { code: ';' }, @@ -34,7 +36,10 @@ ruleTester.run('no-unknown-property', rule, { { code: ';' }, { code: ';' }, { code: ';' }, - { code: ';' }, + { + code: ';', + features: ['jsx namespace'], + }, { code: ';' }, { code: '
;' }, { code: '
;' }, @@ -48,8 +53,8 @@ ruleTester.run('no-unknown-property', rule, { { code: '