`;
@@ -545,20 +545,20 @@ const ATTR_PAREN_NEW_LINE = `
const ATTR_PAREN_NEW_LINE_AUTOFIX = `
`;
@@ -571,10 +571,53 @@ export default () =>
const SFC_NO_PARENS_AUTOFIX = `
export default () => (
-
+
with newline without parentheses eslint crashes
-)`;
+ )`;
+
+const ARROW_WITH_EXPORT = `
+ const Component = () =>
+
+
+ export { Component as default }
+`;
+
+const ARROW_WITH_EXPORT_AUTOFIX = `
+ const Component = () => (
+
+ )
+
+ export { Component as default }
+`;
+
+const ARROW_WITH_LOGICAL = `
+const Component = props => (
+
+)
+`;
+
+const ARROW_WITH_LOGICAL_AUTOFIX = `
+const Component = props => (
+
+)
+`;
function addNewLineSymbols(code) {
return code.replace(/\(\)/g, '>\n)');
@@ -1040,7 +1083,7 @@ ruleTester.run('jsx-wrap-multilines', rule, {
]
}, {
code: DECLARATION_TERNARY_PAREN_FRAGMENT,
- parser: parsers.BABEL_ESLINT,
+ parser: parsers.TYPESCRIPT_ESLINT,
output: addNewLineSymbols(DECLARATION_TERNARY_PAREN_FRAGMENT),
options: [{declaration: 'parens-new-line'}],
errors: [
@@ -1189,5 +1232,23 @@ ruleTester.run('jsx-wrap-multilines', rule, {
output: SFC_NO_PARENS_AUTOFIX,
options: [OPTIONS_ALL_NEW_LINES],
errors: [{message: MISSING_PARENS}]
+ }, {
+ code: ARROW_WITH_EXPORT,
+ output: ARROW_WITH_EXPORT_AUTOFIX,
+ options: [{
+ declaration: 'parens-new-line',
+ assignment: 'parens-new-line',
+ return: 'parens-new-line',
+ arrow: 'parens-new-line',
+ condition: 'parens-new-line',
+ logical: 'ignore',
+ prop: 'ignore'
+ }],
+ errors: [{message: MISSING_PARENS}]
+ }, {
+ code: ARROW_WITH_LOGICAL,
+ output: ARROW_WITH_LOGICAL_AUTOFIX,
+ options: [{logical: 'parens-new-line'}],
+ errors: [{message: MISSING_PARENS}]
}]
});
diff --git a/tests/lib/rules/no-adjacent-inline-elements.js b/tests/lib/rules/no-adjacent-inline-elements.js
new file mode 100644
index 0000000000..1c2e9becc4
--- /dev/null
+++ b/tests/lib/rules/no-adjacent-inline-elements.js
@@ -0,0 +1,107 @@
+/**
+ * @fileoverview Tests for no-adjacent-inline-elements
+ * @author Sean Hayes
+ */
+
+'use strict';
+
+// -----------------------------------------------------------------------------
+// Requirements
+// -----------------------------------------------------------------------------
+
+const RuleTester = require('eslint').RuleTester;
+const rule = require('../../../lib/rules/no-adjacent-inline-elements');
+
+const ERROR = rule.ERROR;
+
+const parserOptions = {
+ ecmaVersion: 6,
+ ecmaFeatures: {
+ experimentalObjectRestSpread: true,
+ jsx: true
+ }
+};
+
+// -----------------------------------------------------------------------------
+// Tests
+// -----------------------------------------------------------------------------
+
+const ruleTester = new RuleTester();
+ruleTester.run('no-adjacent-inline-elements', rule, {
+ valid: [
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: '
;',
+ parserOptions
+ },
+ {
+ code: 'React.createElement("div", null, "some text");',
+ parserOptions
+ },
+ {
+ code: ('React.createElement("div", undefined, [React.createElement("a"), '
+ + '" some text ", React.createElement("a")]);'),
+ parserOptions
+ },
+ {
+ code: 'React.createElement("div", undefined, [React.createElement("a"), " ", React.createElement("a")]);',
+ parserOptions
+ },
+ {
+ code: 'React.createElement(a, b);',
+ parserOptions
+ }
+ ],
+ invalid: [
+ {
+ code: '
;',
+ errors: [{message: ERROR}],
+ parserOptions
+ },
+ {
+ code: '
;',
+ errors: [{message: ERROR}],
+ parserOptions
+ },
+ {
+ code: 'React.createElement("div", undefined, [React.createElement("a"), React.createElement("span")]);',
+ errors: [{message: ERROR}],
+ parserOptions
+ }
+ ]
+});
diff --git a/tests/lib/rules/no-deprecated.js b/tests/lib/rules/no-deprecated.js
index 6e7e029251..587a8aeb7f 100644
--- a/tests/lib/rules/no-deprecated.js
+++ b/tests/lib/rules/no-deprecated.js
@@ -94,7 +94,7 @@ ruleTester.run('no-deprecated', rule, {
componentWillUpdate() {}
}
`,
- settings: {react: {version: '16.998.0'}}
+ settings: {react: {version: '16.8.0'}}
}
],
@@ -222,9 +222,9 @@ ruleTester.run('no-deprecated', rule, {
errors: [
{
message: errorMessage(
- 'componentWillMount', '16.999.0', 'UNSAFE_componentWillMount',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillMount', '16.9.0', 'UNSAFE_componentWillMount',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 3,
@@ -232,18 +232,18 @@ ruleTester.run('no-deprecated', rule, {
},
{
message: errorMessage(
- 'componentWillReceiveProps', '16.999.0', 'UNSAFE_componentWillReceiveProps',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillReceiveProps', '16.9.0', 'UNSAFE_componentWillReceiveProps',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 4,
column: 11
},
{
- message: errorMessage('componentWillUpdate', '16.999.0', 'UNSAFE_componentWillUpdate',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ message: errorMessage('componentWillUpdate', '16.9.0', 'UNSAFE_componentWillUpdate',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 5,
@@ -264,9 +264,9 @@ ruleTester.run('no-deprecated', rule, {
errors: [
{
message: errorMessage(
- 'componentWillMount', '16.999.0', 'UNSAFE_componentWillMount',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillMount', '16.9.0', 'UNSAFE_componentWillMount',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 4,
@@ -274,18 +274,18 @@ ruleTester.run('no-deprecated', rule, {
},
{
message: errorMessage(
- 'componentWillReceiveProps', '16.999.0', 'UNSAFE_componentWillReceiveProps',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillReceiveProps', '16.9.0', 'UNSAFE_componentWillReceiveProps',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 5,
column: 13
},
{
- message: errorMessage('componentWillUpdate', '16.999.0', 'UNSAFE_componentWillUpdate',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ message: errorMessage('componentWillUpdate', '16.9.0', 'UNSAFE_componentWillUpdate',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 6,
@@ -304,9 +304,9 @@ ruleTester.run('no-deprecated', rule, {
errors: [
{
message: errorMessage(
- 'componentWillMount', '16.999.0', 'UNSAFE_componentWillMount',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillMount', '16.9.0', 'UNSAFE_componentWillMount',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 3,
@@ -314,18 +314,18 @@ ruleTester.run('no-deprecated', rule, {
},
{
message: errorMessage(
- 'componentWillReceiveProps', '16.999.0', 'UNSAFE_componentWillReceiveProps',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillReceiveProps', '16.9.0', 'UNSAFE_componentWillReceiveProps',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 4,
column: 11
},
{
- message: errorMessage('componentWillUpdate', '16.999.0', 'UNSAFE_componentWillUpdate',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ message: errorMessage('componentWillUpdate', '16.9.0', 'UNSAFE_componentWillUpdate',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 5,
@@ -344,9 +344,9 @@ ruleTester.run('no-deprecated', rule, {
errors: [
{
message: errorMessage(
- 'componentWillMount', '16.999.0', 'UNSAFE_componentWillMount',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillMount', '16.9.0', 'UNSAFE_componentWillMount',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 3,
@@ -354,18 +354,18 @@ ruleTester.run('no-deprecated', rule, {
},
{
message: errorMessage(
- 'componentWillReceiveProps', '16.999.0', 'UNSAFE_componentWillReceiveProps',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillReceiveProps', '16.9.0', 'UNSAFE_componentWillReceiveProps',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 4,
column: 11
},
{
- message: errorMessage('componentWillUpdate', '16.999.0', 'UNSAFE_componentWillUpdate',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ message: errorMessage('componentWillUpdate', '16.9.0', 'UNSAFE_componentWillUpdate',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 5,
@@ -384,9 +384,9 @@ ruleTester.run('no-deprecated', rule, {
errors: [
{
message: errorMessage(
- 'componentWillMount', '16.999.0', 'UNSAFE_componentWillMount',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillMount', '16.9.0', 'UNSAFE_componentWillMount',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 3,
@@ -394,18 +394,18 @@ ruleTester.run('no-deprecated', rule, {
},
{
message: errorMessage(
- 'componentWillReceiveProps', '16.999.0', 'UNSAFE_componentWillReceiveProps',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillReceiveProps', '16.9.0', 'UNSAFE_componentWillReceiveProps',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 4,
column: 11
},
{
- message: errorMessage('componentWillUpdate', '16.999.0', 'UNSAFE_componentWillUpdate',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ message: errorMessage('componentWillUpdate', '16.9.0', 'UNSAFE_componentWillUpdate',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 5,
@@ -424,9 +424,9 @@ ruleTester.run('no-deprecated', rule, {
errors: [
{
message: errorMessage(
- 'componentWillMount', '16.999.0', 'UNSAFE_componentWillMount',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillMount', '16.9.0', 'UNSAFE_componentWillMount',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 3,
@@ -434,18 +434,18 @@ ruleTester.run('no-deprecated', rule, {
},
{
message: errorMessage(
- 'componentWillReceiveProps', '16.999.0', 'UNSAFE_componentWillReceiveProps',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillReceiveProps', '16.9.0', 'UNSAFE_componentWillReceiveProps',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 4,
column: 11
},
{
- message: errorMessage('componentWillUpdate', '16.999.0', 'UNSAFE_componentWillUpdate',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ message: errorMessage('componentWillUpdate', '16.9.0', 'UNSAFE_componentWillUpdate',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 5,
@@ -465,9 +465,9 @@ ruleTester.run('no-deprecated', rule, {
errors: [
{
message: errorMessage(
- 'componentWillMount', '16.999.0', 'UNSAFE_componentWillMount',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillMount', '16.9.0', 'UNSAFE_componentWillMount',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 4,
@@ -475,18 +475,18 @@ ruleTester.run('no-deprecated', rule, {
},
{
message: errorMessage(
- 'componentWillReceiveProps', '16.999.0', 'UNSAFE_componentWillReceiveProps',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ 'componentWillReceiveProps', '16.9.0', 'UNSAFE_componentWillReceiveProps',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 5,
column: 11
},
{
- message: errorMessage('componentWillUpdate', '16.999.0', 'UNSAFE_componentWillUpdate',
- 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. ' +
- 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
+ message: errorMessage('componentWillUpdate', '16.9.0', 'UNSAFE_componentWillUpdate',
+ 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. '
+ + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.'
),
type: 'Identifier',
line: 6,
diff --git a/tests/lib/rules/no-multi-comp.js b/tests/lib/rules/no-multi-comp.js
index 9728276c80..a4bad0c10b 100644
--- a/tests/lib/rules/no-multi-comp.js
+++ b/tests/lib/rules/no-multi-comp.js
@@ -116,6 +116,111 @@ ruleTester.run('no-multi-comp', rule, {
options: [{
ignoreStateless: true
}]
+ }, {
+ code: `
+ class StoreListItem extends React.PureComponent {
+ // A bunch of stuff here
+ }
+ export default React.forwardRef((props, ref) =>
);
+ `,
+ options: [{
+ ignoreStateless: false
+ }]
+ }, {
+ code: `
+ class StoreListItem extends React.PureComponent {
+ // A bunch of stuff here
+ }
+ export default React.forwardRef((props, ref) => {
+ return
+ });
+ `,
+ options: [{
+ ignoreStateless: false
+ }]
+ }, {
+ code: `
+ const HelloComponent = (props) => {
+ return
;
+ }
+ export default React.forwardRef((props, ref) =>
);
+ `,
+ options: [{
+ ignoreStateless: false
+ }]
+ }, {
+ code: `
+ class StoreListItem extends React.PureComponent {
+ // A bunch of stuff here
+ }
+ export default React.forwardRef(
+ function myFunction(props, ref) {
+ return
;
+ }
+ );
+ `,
+ options: [{
+ ignoreStateless: false
+ }]
+ }, {
+ code: `
+ class StoreListItem extends React.PureComponent {
+ // A bunch of stuff here
+ }
+ export default React.forwardRef((props, ref) =>
);
+ `,
+ options: [{
+ ignoreStateless: true
+ }]
+ }, {
+ code: `
+ class StoreListItem extends React.PureComponent {
+ // A bunch of stuff here
+ }
+ export default React.forwardRef((props, ref) => {
+ return
+ });
+ `,
+ options: [{
+ ignoreStateless: true
+ }]
+ }, {
+ code: `
+ const HelloComponent = (props) => {
+ return
;
+ }
+ export default React.forwardRef((props, ref) =>
);
+ `,
+ options: [{
+ ignoreStateless: true
+ }]
+ }, {
+ code: `
+ const HelloComponent = (props) => {
+ return
;
+ }
+ class StoreListItem extends React.PureComponent {
+ // A bunch of stuff here
+ }
+ export default React.forwardRef(
+ function myFunction(props, ref) {
+ return
;
+ }
+ );
+ `,
+ options: [{
+ ignoreStateless: true
+ }]
+ }, {
+ code: `
+ const HelloComponent = (props) => {
+ return
;
+ }
+ export default React.memo((props, ref) =>
);
+ `,
+ options: [{
+ ignoreStateless: false
+ }]
}],
invalid: [{
@@ -207,5 +312,69 @@ ruleTester.run('no-multi-comp', rule, {
message: 'Declare only one React component per file',
line: 6
}]
+ },
+ {
+ code: `
+ exports.Foo = function Foo() {
+ return <>>
+ }
+
+ exports.createSomeComponent = function createSomeComponent(opts) {
+ return function Foo() {
+ return <>{opts.a}>
+ }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ errors: [{
+ message: 'Declare only one React component per file',
+ line: 7
+ }]
+ },
+ {
+ code: `
+ class StoreListItem extends React.PureComponent {
+ // A bunch of stuff here
+ }
+ export default React.forwardRef((props, ref) =>
);
+ `,
+ options: [{
+ ignoreStateless: false
+ }],
+ parser: parsers.BABEL_ESLINT,
+ errors: [{
+ message: 'Declare only one React component per file',
+ line: 5
+ }]
+ }, {
+ code: `
+ const HelloComponent = (props) => {
+ return
;
+ }
+ const HelloComponent2 = React.forwardRef((props, ref) =>
);
+ `,
+ options: [{
+ ignoreStateless: false
+ }],
+ parser: parsers.BABEL_ESLINT,
+ errors: [{
+ message: 'Declare only one React component per file',
+ line: 5
+ }]
+ }, {
+ code: `
+ const HelloComponent = (0, (props) => {
+ return
;
+ });
+ const HelloComponent2 = React.forwardRef((props, ref) => <>
>);
+ `,
+ options: [{
+ ignoreStateless: false
+ }],
+ parser: parsers.BABEL_ESLINT,
+ errors: [{
+ message: 'Declare only one React component per file',
+ line: 5
+ }]
}]
});
diff --git a/tests/lib/rules/no-redundant-should-component-update.js b/tests/lib/rules/no-redundant-should-component-update.js
index 34c9724413..de3a37518b 100644
--- a/tests/lib/rules/no-redundant-should-component-update.js
+++ b/tests/lib/rules/no-redundant-should-component-update.js
@@ -44,22 +44,23 @@ ruleTester.run('no-redundant-should-component-update', rule, {
{
code: `
class Foo extends React.Component {
- shouldComponentUpdate = () => {
+ shouldComponentUpdate() {
return true;
}
}
`,
- parser: parsers.BABEL_ESLINT,
- parserOptions
+ parserOptions,
+ parser: parsers.BABEL_ESLINT
},
{
code: `
class Foo extends React.Component {
- shouldComponentUpdate() {
+ shouldComponentUpdate = () => {
return true;
}
}
`,
+ parser: parsers.BABEL_ESLINT,
parserOptions
},
{
diff --git a/tests/lib/rules/no-render-return-value.js b/tests/lib/rules/no-render-return-value.js
index ab7c37190d..919da8b025 100644
--- a/tests/lib/rules/no-render-return-value.js
+++ b/tests/lib/rules/no-render-return-value.js
@@ -96,6 +96,16 @@ ruleTester.run('no-render-return-value', rule, {
errors: [{
message: 'Do not depend on the return value from ReactDOM.render'
}]
+ }, {
+ code: 'this.o = ReactDOM.render(
, document.body);',
+ errors: [{
+ message: 'Do not depend on the return value from ReactDOM.render'
+ }]
+ }, {
+ code: 'var v; v = ReactDOM.render(
, document.body);',
+ errors: [{
+ message: 'Do not depend on the return value from ReactDOM.render'
+ }]
}, {
code: 'var inst = React.render(
, document.body);',
settings: {
diff --git a/tests/lib/rules/no-this-in-sfc.js b/tests/lib/rules/no-this-in-sfc.js
index 1688d3f8a3..f672d40109 100644
--- a/tests/lib/rules/no-this-in-sfc.js
+++ b/tests/lib/rules/no-this-in-sfc.js
@@ -8,7 +8,7 @@
// Constants
// ------------------------------------------------------------------------------
-const ERROR_MESSAGE = 'Stateless functional components should not use this';
+const ERROR_MESSAGE = 'Stateless functional components should not use `this`';
// ------------------------------------------------------------------------------
// Requirements
@@ -217,13 +217,6 @@ ruleTester.run('no-this-in-sfc', rule, {
return
{this.props.foo}
;
}`,
errors: [{message: ERROR_MESSAGE}, {message: ERROR_MESSAGE}]
- }, {
- code: `
- () => {
- this.something();
- return null;
- }`,
- errors: [{message: ERROR_MESSAGE}]
}, {
code: `
class Foo {
diff --git a/tests/lib/rules/no-typos.js b/tests/lib/rules/no-typos.js
index 0a001e304e..c814c4826e 100644
--- a/tests/lib/rules/no-typos.js
+++ b/tests/lib/rules/no-typos.js
@@ -27,7 +27,8 @@ const parserOptions = {
const ERROR_MESSAGE = 'Typo in static class property declaration';
const ERROR_MESSAGE_ES5 = 'Typo in property declaration';
-const ERROR_MESSAGE_LIFECYCLE_METHOD = 'Typo in component lifecycle method declaration';
+const ERROR_MESSAGE_LIFECYCLE_METHOD = (actual, expected) => `Typo in component lifecycle method declaration: ${actual} should be ${expected}`;
+const ERROR_MESSAGE_STATIC = (method) => `Lifecycle method should be static: ${method}`;
const ruleTester = new RuleTester();
ruleTester.run('no-typos', rule, {
@@ -190,6 +191,7 @@ ruleTester.run('no-typos', rule, {
}, {
code: `
class Hello extends React.Component {
+ static getDerivedStateFromProps() { }
componentWillMount() { }
componentDidMount() { }
componentWillReceiveProps() { }
@@ -203,6 +205,14 @@ ruleTester.run('no-typos', rule, {
}
`,
parserOptions
+ }, {
+ code: `
+ class Hello extends React.Component {
+ "componentDidMount"() { }
+ "my-method"() { }
+ }
+ `,
+ parserOptions
}, {
code: `
class MyClass {
@@ -333,19 +343,6 @@ ruleTester.run('no-typos', rule, {
`,
parser: parsers.BABEL_ESLINT,
parserOptions
- }, {
- code: `
- import PropTypes from "prop-types";
- class Component extends React.Component {};
- Component.propTypes = {
- a: PropTypes.oneOf([
- 'hello',
- 'hi'
- ])
- }
- `,
- parser: parsers.BABEL_ESLINT,
- parserOptions
}, {
code: `
import PropTypes from "prop-types";
@@ -406,21 +403,6 @@ ruleTester.run('no-typos', rule, {
}
`,
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
}, {
code: `
import PropTypes from "prop-types";
@@ -646,21 +628,21 @@ ruleTester.run('no-typos', rule, {
`,
parser: parsers.BABEL_ESLINT,
parserOptions,
- errors: [{message: ERROR_MESSAGE}]
+ errors: [{message: ERROR_MESSAGE, type: 'Identifier'}]
}, {
code: `
class Component extends React.Component {}
Component.PropTypes = {}
`,
parserOptions,
- errors: [{message: ERROR_MESSAGE}]
+ errors: [{message: ERROR_MESSAGE, type: 'Identifier'}]
}, {
code: `
function MyComponent() { return (
{this.props.myProp}
) }
MyComponent.PropTypes = {}
`,
parserOptions,
- errors: [{message: ERROR_MESSAGE}]
+ errors: [{message: ERROR_MESSAGE, type: 'Identifier'}]
}, {
code: `
class Component extends React.Component {
@@ -692,7 +674,7 @@ ruleTester.run('no-typos', rule, {
`,
parser: parsers.BABEL_ESLINT,
parserOptions,
- errors: [{message: ERROR_MESSAGE}]
+ errors: [{message: ERROR_MESSAGE, type: 'Identifier'}]
}, {
code: `
class Component extends React.Component {}
@@ -784,21 +766,21 @@ ruleTester.run('no-typos', rule, {
`,
parser: parsers.BABEL_ESLINT,
parserOptions,
- errors: [{message: ERROR_MESSAGE}]
+ errors: [{message: ERROR_MESSAGE, type: 'Identifier'}]
}, {
code: `
class Component extends React.Component {}
Component.DefaultProps = {}
`,
parserOptions,
- errors: [{message: ERROR_MESSAGE}]
+ errors: [{message: ERROR_MESSAGE, type: 'Identifier'}]
}, {
code: `
function MyComponent() { return (
{this.props.myProp}
) }
MyComponent.DefaultProps = {}
`,
parserOptions,
- errors: [{message: ERROR_MESSAGE}]
+ errors: [{message: ERROR_MESSAGE, type: 'Identifier'}]
}, {
code: `
class Component extends React.Component {
@@ -860,43 +842,43 @@ ruleTester.run('no-typos', rule, {
`,
parserOptions,
errors: [{
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('GetDerivedStateFromProps', 'getDerivedStateFromProps'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillMount', 'componentWillMount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('UNSAFE_ComponentWillMount', 'UNSAFE_componentWillMount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentDidMount', 'componentDidMount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillReceiveProps', 'componentWillReceiveProps'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('UNSAFE_ComponentWillReceiveProps', 'UNSAFE_componentWillReceiveProps'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ShouldComponentUpdate', 'shouldComponentUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillUpdate', 'componentWillUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('UNSAFE_ComponentWillUpdate', 'UNSAFE_componentWillUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('GetSnapshotBeforeUpdate', 'getSnapshotBeforeUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentDidUpdate', 'componentDidUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentDidCatch', 'componentDidCatch'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillUnmount', 'componentWillUnmount'),
type: 'MethodDefinition'
}]
}, {
@@ -922,46 +904,46 @@ ruleTester.run('no-typos', rule, {
`,
parserOptions,
errors: [{
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Getderivedstatefromprops', 'getDerivedStateFromProps'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Componentwillmount', 'componentWillMount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('UNSAFE_Componentwillmount', 'UNSAFE_componentWillMount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Componentdidmount', 'componentDidMount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Componentwillreceiveprops', 'componentWillReceiveProps'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('UNSAFE_Componentwillreceiveprops', 'UNSAFE_componentWillReceiveProps'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Shouldcomponentupdate', 'shouldComponentUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Componentwillupdate', 'componentWillUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('UNSAFE_Componentwillupdate', 'UNSAFE_componentWillUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Getsnapshotbeforeupdate', 'getSnapshotBeforeUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Componentdidupdate', 'componentDidUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Componentdidcatch', 'componentDidCatch'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Componentwillunmount', 'componentWillUnmount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('Render', 'render'),
type: 'MethodDefinition'
}]
}, {
@@ -987,43 +969,43 @@ ruleTester.run('no-typos', rule, {
`,
parserOptions,
errors: [{
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('getderivedstatefromprops', 'getDerivedStateFromProps'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('componentwillmount', 'componentWillMount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('unsafe_componentwillmount', 'UNSAFE_componentWillMount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('componentdidmount', 'componentDidMount'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('componentwillreceiveprops', 'componentWillReceiveProps'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('unsafe_componentwillreceiveprops', 'UNSAFE_componentWillReceiveProps'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('shouldcomponentupdate', 'shouldComponentUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('componentwillupdate', 'componentWillUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('unsafe_componentwillupdate', 'UNSAFE_componentWillUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('getsnapshotbeforeupdate', 'getSnapshotBeforeUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('componentdidupdate', 'componentDidUpdate'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('componentdidcatch', 'componentDidCatch'),
type: 'MethodDefinition'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('componentwillunmount', 'componentWillUnmount'),
type: 'MethodDefinition'
}]
}, {
@@ -1366,6 +1348,7 @@ ruleTester.run('no-typos', rule, {
}).isrequired
}
`,
+ parser: parsers.BABEL_ESLINT,
parserOptions,
errors: [{
message: 'Typo in prop type chain qualifier: isrequired'
@@ -1594,35 +1577,62 @@ ruleTester.run('no-typos', rule, {
parserOptions,
errors: [{
message: ERROR_MESSAGE_ES5,
- type: 'ObjectExpression'
+ type: 'Identifier'
}, {
message: ERROR_MESSAGE_ES5,
- type: 'ObjectExpression'
+ type: 'Identifier'
}, {
message: ERROR_MESSAGE_ES5,
- type: 'ObjectExpression'
+ type: 'Identifier'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillMount', 'componentWillMount'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentDidMount', 'componentDidMount'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillReceiveProps', 'componentWillReceiveProps'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ShouldComponentUpdate', 'shouldComponentUpdate'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillUpdate', 'componentWillUpdate'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentDidUpdate', 'componentDidUpdate'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillUnmount', 'componentWillUnmount'),
type: 'Property'
}]
+ }, {
+ code: `
+ class Hello extends React.Component {
+ getDerivedStateFromProps() { }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ parserOptions,
+ errors: [{
+ message: ERROR_MESSAGE_STATIC('getDerivedStateFromProps'),
+ type: 'MethodDefinition'
+ }]
+ }, {
+ code: `
+ class Hello extends React.Component {
+ GetDerivedStateFromProps() { }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ parserOptions,
+ errors: [{
+ message: ERROR_MESSAGE_STATIC('GetDerivedStateFromProps'),
+ type: 'MethodDefinition'
+ }, {
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('GetDerivedStateFromProps', 'getDerivedStateFromProps'),
+ type: 'MethodDefinition'
+ }]
}, {
code: `
import React from 'react';
@@ -1646,33 +1656,33 @@ ruleTester.run('no-typos', rule, {
parserOptions,
errors: [{
message: ERROR_MESSAGE_ES5,
- type: 'ObjectExpression'
+ type: 'Identifier'
}, {
message: ERROR_MESSAGE_ES5,
- type: 'ObjectExpression'
+ type: 'Identifier'
}, {
message: ERROR_MESSAGE_ES5,
- type: 'ObjectExpression'
+ type: 'Identifier'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillMount', 'componentWillMount'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentDidMount', 'componentDidMount'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillReceiveProps', 'componentWillReceiveProps'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ShouldComponentUpdate', 'shouldComponentUpdate'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillUpdate', 'componentWillUpdate'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentDidUpdate', 'componentDidUpdate'),
type: 'Property'
}, {
- message: ERROR_MESSAGE_LIFECYCLE_METHOD,
+ message: ERROR_MESSAGE_LIFECYCLE_METHOD('ComponentWillUnmount', 'componentWillUnmount'),
type: 'Property'
}]
/*
diff --git a/tests/lib/rules/no-unescaped-entities.js b/tests/lib/rules/no-unescaped-entities.js
index b10f5555e0..1b47aa2b63 100644
--- a/tests/lib/rules/no-unescaped-entities.js
+++ b/tests/lib/rules/no-unescaped-entities.js
@@ -9,6 +9,14 @@
// Requirements
// ------------------------------------------------------------------------------
+const semver = require('semver');
+
+let allowsInvalidJSX = false;
+try {
+ // eslint-disable-next-line import/no-extraneous-dependencies, global-require
+ allowsInvalidJSX = semver.satisfies(require('acorn-jsx/package.json').version, '< 5.2');
+} catch (e) { /**/ }
+
const RuleTester = require('eslint').RuleTester;
const rule = require('../../../lib/rules/no-unescaped-entities');
@@ -107,7 +115,7 @@ ruleTester.run('no-unescaped-entities', rule, {
],
invalid: [
- {
+ (allowsInvalidJSX && {
code: `
var Hello = createReactClass({
render: function() {
@@ -116,7 +124,7 @@ ruleTester.run('no-unescaped-entities', rule, {
});
`,
errors: [{message: '`>` can be escaped with `>`.'}]
- }, {
+ }), {
code: `
var Hello = createReactClass({
render: function() {
@@ -126,7 +134,7 @@ ruleTester.run('no-unescaped-entities', rule, {
`,
parser: parsers.BABEL_ESLINT,
errors: [{message: '`>` can be escaped with `>`.'}]
- }, {
+ }, (allowsInvalidJSX && {
code: `
var Hello = createReactClass({
render: function() {
@@ -137,7 +145,7 @@ ruleTester.run('no-unescaped-entities', rule, {
});
`,
errors: [{message: '`>` can be escaped with `>`.'}]
- }, {
+ }), {
code: `
var Hello = createReactClass({
render: function() {
@@ -158,7 +166,7 @@ ruleTester.run('no-unescaped-entities', rule, {
});
`,
errors: [{message: '`\'` can be escaped with `'`, `‘`, `'`, `’`.'}]
- }, {
+ }, (allowsInvalidJSX && {
code: `
var Hello = createReactClass({
render: function() {
@@ -171,7 +179,7 @@ ruleTester.run('no-unescaped-entities', rule, {
{message: '`>` can be escaped with `>`.'},
{message: '`>` can be escaped with `>`.'}
]
- }, {
+ }), (allowsInvalidJSX && {
code: `
var Hello = createReactClass({
render: function() {
@@ -180,7 +188,7 @@ ruleTester.run('no-unescaped-entities', rule, {
});
`,
errors: [{message: '`}` can be escaped with `}`.'}]
- }, {
+ }), {
code: `
var Hello = createReactClass({
render: function() {
@@ -231,5 +239,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 8bfdd9d61a..21197a4e06 100644
--- a/tests/lib/rules/no-unknown-property.js
+++ b/tests/lib/rules/no-unknown-property.js
@@ -85,10 +85,12 @@ ruleTester.run('no-unknown-property', rule, {
errors: [{message: 'Unknown property \'clip-path\' found, use \'clipPath\' instead'}]
}, {
code: '',
- errors: [{message: 'Unknown property \'crossorigin\' found, use \'crossOrigin\' instead'}]
+ errors: [{message: 'Unknown property \'crossorigin\' found, use \'crossOrigin\' instead'}],
+ output: ''
}, {
code: '
',
- errors: [{message: 'Unknown property \'crossorigin\' found, use \'crossOrigin\' instead'}]
+ errors: [{message: 'Unknown property \'crossorigin\' found, use \'crossOrigin\' instead'}],
+ output: '
'
}, {
code: '
',
errors: [{message: 'Invalid property \'crossOrigin\' found on tag \'div\', but it is only allowed on: script, img, video, audio, link'}]
diff --git a/tests/lib/rules/no-unused-prop-types.js b/tests/lib/rules/no-unused-prop-types.js
index ab327ce4b8..78b36eee4a 100644
--- a/tests/lib/rules/no-unused-prop-types.js
+++ b/tests/lib/rules/no-unused-prop-types.js
@@ -1094,6 +1094,30 @@ ruleTester.run('no-unused-prop-types', rule, {
'}'
].join('\n'),
parser: parsers.BABEL_ESLINT
+ }, {
+ code: [
+ 'type Props = {notTarget: string};',
+ 'class Hello extends React.Component {',
+ ' props: Props;',
+ ' onEvent({ target }: { target: Object }) {};',
+ ' render () {',
+ ' return
Hello {this.props.notTarget}
;',
+ ' }',
+ '}'
+ ].join('\n'),
+ parser: parsers.BABEL_ESLINT
+ }, {
+ code: [
+ 'type Props = {notTarget: string};',
+ 'class Hello extends React.Component {',
+ ' props: Props;',
+ ' onEvent(infos: { target: Object }) {};',
+ ' render () {',
+ ' return
Hello {this.props.notTarget}
;',
+ ' }',
+ '}'
+ ].join('\n'),
+ parser: parsers.BABEL_ESLINT
}, {
code: [
'class Hello extends React.Component {',
@@ -1825,6 +1849,18 @@ ruleTester.run('no-unused-prop-types', rule, {
' return
;',
'};'
].join('\n')
+ }, {
+ // Nested destructuring; issue 2424
+ code: `
+ function SomeComponent(props) {
+ const {aaa: {bbb}} = props;
+ return
{bbb}
;
+ }
+
+ SomeComponent.propTypes = {
+ aaa: somePropType,
+ };
+ `
}, {
// `no-unused-prop-types` in jsx expressions - [Issue #885]
code: [
@@ -1856,6 +1892,22 @@ ruleTester.run('no-unused-prop-types', rule, {
' previousPage: PropTypes.func.isRequired,',
'};'
].join('\n')
+ }, {
+ // issue 2350
+ code: `
+ function Foo(props) {
+ useEffect(() => {
+ const { a } = props;
+ document.title = a;
+ });
+
+ return
;
+ }
+
+ Foo.propTypes = {
+ a: PropTypes.string,
+ }
+ `
}, {
code: [
'class Hello extends Component {',
@@ -2710,6 +2762,17 @@ ruleTester.run('no-unused-prop-types', rule, {
};
`,
parser: parsers.BABEL_ESLINT
+ }, {
+ code: [
+ 'type Props = $ReadOnly<{foo: number}>;',
+ 'class Hello extends React.Component {',
+ ' props: Props;',
+ ' render () {',
+ ' return
{this.props.foo}
;',
+ ' }',
+ '}'
+ ].join('\n'),
+ parser: parsers.BABEL_ESLINT
}, {
// issue #933
code: `
@@ -3062,8 +3125,7 @@ ruleTester.run('no-unused-prop-types', rule, {
}
`,
parser: parsers.BABEL_ESLINT
- },
- {
+ }, {
code: `
export default class Foo extends React.Component {
render() {
@@ -3073,6 +3135,82 @@ ruleTester.run('no-unused-prop-types', rule, {
Foo.defaultProps = Object.assign({});
`
+ }, {
+ code: `
+ const Foo = (props) => {
+ const { foo } = props as unknown;
+ (props as unknown).bar as unknown;
+
+ return <>>;
+ };
+
+ Foo.propTypes = {
+ foo,
+ bar,
+ };
+ `,
+ parser: parsers.TYPESCRIPT_ESLINT
+ }, {
+ code: `
+ class Foo extends React.Component {
+ static propTypes = {
+ prevProp,
+ nextProp,
+ setStateProp,
+ thisPropsAliasDestructProp,
+ thisPropsAliasProp,
+ thisDestructPropsAliasDestructProp,
+ thisDestructPropsAliasProp,
+ thisDestructPropsDestructProp,
+ thisPropsDestructProp,
+ thisPropsProp,
+ };
+
+ componentDidUpdate(prevProps) {
+ (prevProps as unknown).prevProp as unknown;
+ }
+
+ shouldComponentUpdate(nextProps) {
+ (nextProps as unknown).nextProp as unknown;
+ }
+
+ stateProps() {
+ ((this as unknown).setState as unknown)((_, props) => (props as unknown).setStateProp as unknown);
+ }
+
+ thisPropsAlias() {
+ const props = (this as unknown).props as unknown;
+
+ const { thisPropsAliasDestructProp } = props as unknown;
+ (props as unknown).thisPropsAliasProp as unknown;
+ }
+
+ thisDestructPropsAlias() {
+ const { props } = this as unknown;
+
+ const { thisDestructPropsAliasDestructProp } = props as unknown;
+ (props as unknown).thisDestructPropsAliasProp as unknown;
+ }
+
+ render() {
+ const { props: { thisDestructPropsDestructProp } } = this as unknown;
+ const { thisPropsDestructProp } = (this as unknown).props as unknown;
+ ((this as unknown).props as unknown).thisPropsProp as unknown;
+
+ return null;
+ }
+ }
+ `,
+ parser: parsers.TYPESCRIPT_ESLINT
+ },
+ {
+ code: [
+ 'declare class Thing {',
+ ' constructor({ id }: { id: string });',
+ '}',
+ 'export default Thing;'
+ ].join('\n'),
+ parser: parsers.TYPESCRIPT_ESLINT
}
],
@@ -3091,7 +3229,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -3107,7 +3245,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'name\' PropType is defined but prop is never used',
line: 3,
- column: 11
+ column: 5
}]
}, {
code: [
@@ -3124,7 +3262,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'name\' PropType is defined but prop is never used',
line: 3,
- column: 11
+ column: 5
}]
}, {
code: [
@@ -3656,6 +3794,20 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [
{message: '\'unused\' PropType is defined but prop is never used'}
]
+ }, {
+ code: [
+ 'type Props = $ReadOnly<{unused: Object;}>;',
+ 'class Hello extends React.Component {',
+ ' props: Props;',
+ ' render () {',
+ ' return
Hello {this.props.firstname}
;',
+ ' }',
+ '}'
+ ].join('\n'),
+ parser: parsers.BABEL_ESLINT,
+ errors: [
+ {message: '\'unused\' PropType is defined but prop is never used'}
+ ]
}, {
code: `
type PropsA = { a: string }
@@ -3909,7 +4061,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -3927,7 +4079,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -3945,7 +4097,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -3962,7 +4114,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -3980,7 +4132,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -3997,7 +4149,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -4015,7 +4167,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -4032,7 +4184,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -4050,7 +4202,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -4067,7 +4219,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unused\' PropType is defined but prop is never used',
line: 3,
- column: 13
+ column: 5
}]
}, {
code: [
@@ -4084,7 +4236,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'something\' PropType is defined but prop is never used',
line: 3,
- column: 16
+ column: 5
}]
}, {
code: [
@@ -4100,7 +4252,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'something\' PropType is defined but prop is never used',
line: 3,
- column: 16
+ column: 5
}]
}, {
code: [
@@ -4121,7 +4273,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'bar\' PropType is defined but prop is never used',
line: 4,
- column: 10
+ column: 5
}]
}, {
// Multiple props used inside of an async class property
@@ -4142,7 +4294,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'baz\' PropType is defined but prop is never used',
line: 5,
- column: 10
+ column: 5
}]
}, {
code: [
@@ -4161,7 +4313,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'bar\' PropType is defined but prop is never used',
line: 10,
- column: 8
+ column: 3
}]
}, {
code: [
@@ -4182,7 +4334,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'bar\' PropType is defined but prop is never used',
line: 4,
- column: 10
+ column: 5
}]
}, {
// Multiple destructured props inside of async class property
@@ -4223,7 +4375,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'bar\' PropType is defined but prop is never used',
line: 4,
- column: 10
+ column: 5
}]
}, {
code: [
@@ -4242,7 +4394,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'bar\' PropType is defined but prop is never used',
line: 10,
- column: 8
+ column: 3
}]
}, {
code: [
@@ -4263,7 +4415,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'bar\' PropType is defined but prop is never used',
line: 4,
- column: 10
+ column: 5
}]
}, {
// Multiple destructured props inside of async class method
@@ -4285,7 +4437,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'baz\' PropType is defined but prop is never used',
line: 5,
- column: 10
+ column: 5
}]
}, {
// factory functions that return async functions
@@ -4308,7 +4460,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'baz\' PropType is defined but prop is never used',
line: 5,
- column: 10
+ column: 5
}]
}, {
code: [
@@ -4327,7 +4479,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'bar\' PropType is defined but prop is never used',
line: 10,
- column: 8
+ column: 3
}]
}, {
code: [
@@ -4346,7 +4498,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'bar\' PropType is defined but prop is never used',
line: 10,
- column: 8
+ column: 3
}],
settings: {
propWrapperFunctions: ['forbidExtraProps']
@@ -4369,7 +4521,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'bar\' PropType is defined but prop is never used',
line: 4,
- column: 10
+ column: 5
}],
settings: {
propWrapperFunctions: ['forbidExtraProps']
@@ -4395,7 +4547,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'foo\' PropType is defined but prop is never used',
line: 3,
- column: 10
+ column: 5
}]
}, {
// Multiple props used inside of an async function
@@ -4419,7 +4571,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'baz\' PropType is defined but prop is never used',
line: 13,
- column: 8
+ column: 3
}]
}, {
// Multiple props used inside of an async arrow function
@@ -4443,7 +4595,7 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'foo\' PropType is defined but prop is never used',
line: 11,
- column: 8
+ column: 3
}]
}, {
// None of the props are used issue #1162
@@ -4566,6 +4718,29 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'aProp\' PropType is defined but prop is never used'
}]
+ }, {
+ // issue #2138
+ code: `
+ type UsedProps = {|
+ usedProp: number,
+ |};
+
+ type UnusedProps = {|
+ unusedProp: number,
+ |};
+
+ type Props = {| ...UsedProps, ...UnusedProps |};
+
+ function MyComponent({ usedProp, notOne }: Props) {
+ return
{usedProp}
;
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ errors: [{
+ message: "'unusedProp' PropType is defined but prop is never used",
+ line: 7,
+ column: 11
+ }]
}, {
code: `
type Props = {
@@ -4949,40 +5124,6 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'lastname\' PropType is defined but prop is never used'
}]
- }, {
- code: [
- 'type Person = {',
- ' ...data,',
- ' lastname: string',
- '};',
- 'class Hello extends React.Component {',
- ' props: Person;',
- ' render () {',
- ' return
Hello {this.props.firstname}
;',
- ' }',
- '}'
- ].join('\n'),
- parser: parsers.BABEL_ESLINT,
- errors: [{
- message: '\'lastname\' PropType is defined but prop is never used'
- }]
- }, {
- code: [
- 'type Person = {|',
- ' ...data,',
- ' lastname: string',
- '|};',
- 'class Hello extends React.Component {',
- ' props: Person;',
- ' render () {',
- ' return
Hello {this.props.firstname}
;',
- ' }',
- '}'
- ].join('\n'),
- parser: parsers.BABEL_ESLINT,
- errors: [{
- message: '\'lastname\' PropType is defined but prop is never used'
- }]
}, {
code: [
'class Hello extends React.Component {',
@@ -5039,6 +5180,21 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'person.lastname\' PropType is defined but prop is never used'
}]
+ }, {
+ code: [
+ 'type Props = {notTarget: string, unused: string};',
+ 'class Hello extends React.Component {',
+ ' props: Props;',
+ ' onEvent = ({ target }: { target: Object }) => {};',
+ ' render () {',
+ ' return
Hello {this.props.notTarget}
;',
+ ' }',
+ '}'
+ ].join('\n'),
+ parser: parsers.BABEL_ESLINT,
+ errors: [
+ {message: '\'unused\' PropType is defined but prop is never used'}
+ ]
}, {
code: `
import PropTypes from 'prop-types';
@@ -5063,6 +5219,99 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'unUsedProp\' PropType is defined but prop is never used'
}]
+ }, {
+ code: `
+ const Foo = (props) => {
+ const { foo } = props as unknown;
+ (props as unknown).bar as unknown;
+
+ return <>>;
+ };
+
+ Foo.propTypes = {
+ fooUnused,
+ barUnused,
+ };
+ `,
+ parser: parsers.TYPESCRIPT_ESLINT,
+ errors: [{
+ message: '\'fooUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'barUnused\' PropType is defined but prop is never used'
+ }]
+ }, {
+ code: `
+ class Foo extends React.Component {
+ static propTypes = {
+ prevPropUnused,
+ nextPropUnused,
+ setStatePropUnused,
+ thisPropsAliasDestructPropUnused,
+ thisPropsAliasPropUnused,
+ thisDestructPropsAliasDestructPropUnused,
+ thisDestructPropsAliasPropUnused,
+ thisDestructPropsDestructPropUnused,
+ thisPropsDestructPropUnused,
+ thisPropsPropUnused,
+ };
+
+ componentDidUpdate(prevProps) {
+ (prevProps as unknown).prevProp as unknown;
+ }
+
+ shouldComponentUpdate(nextProps) {
+ (nextProps as unknown).nextProp as unknown;
+ }
+
+ stateProps() {
+ ((this as unknown).setState as unknown)((_, props) => (props as unknown).setStateProp as unknown);
+ }
+
+ thisPropsAlias() {
+ const props = (this as unknown).props as unknown;
+
+ const { thisPropsAliasDestructProp } = props as unknown;
+ (props as unknown).thisPropsAliasProp as unknown;
+ }
+
+ thisDestructPropsAlias() {
+ const { props } = this as unknown;
+
+ const { thisDestructPropsAliasDestructProp } = props as unknown;
+ (props as unknown).thisDestructPropsAliasProp as unknown;
+ }
+
+ render() {
+ const { props: { thisDestructPropsDestructProp } } = this as unknown;
+ const { thisPropsDestructProp } = (this as unknown).props as unknown;
+ ((this as unknown).props as unknown).thisPropsProp as unknown;
+
+ return null;
+ }
+ }
+ `,
+ parser: parsers.TYPESCRIPT_ESLINT,
+ errors: [{
+ message: '\'prevPropUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'nextPropUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'setStatePropUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'thisPropsAliasDestructPropUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'thisPropsAliasPropUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'thisDestructPropsAliasDestructPropUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'thisDestructPropsAliasPropUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'thisDestructPropsDestructPropUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'thisPropsDestructPropUnused\' PropType is defined but prop is never used'
+ }, {
+ message: '\'thisPropsPropUnused\' PropType is defined but prop is never used'
+ }]
}
/* , {
diff --git a/tests/lib/rules/no-unused-state.js b/tests/lib/rules/no-unused-state.js
index cf57dd1ac4..eada128aa9 100644
--- a/tests/lib/rules/no-unused-state.js
+++ b/tests/lib/rules/no-unused-state.js
@@ -19,13 +19,13 @@ const parserOptions = {
const eslintTester = new RuleTester({parserOptions});
function getErrorMessages(unusedFields) {
- return unusedFields.map(field => ({
+ return unusedFields.map((field) => ({
message: `Unused state field: '${field}'`
}));
}
eslintTester.run('no-unused-state', rule, {
- valid: [
+ valid: [].concat(
`function StatelessFnUnaffectedTest(props) {
return
;
};`,
@@ -231,6 +231,28 @@ eslintTester.run('no-unused-state', rule, {
}
}`,
parser: parsers.BABEL_ESLINT
+ }, parsers.TS([{
+ code: `
+ class OptionalChaining extends React.Component {
+ constructor() {
+ this.state = { foo: 0 };
+ }
+ render() {
+ return
;
+ }
+ }`,
+ parser: parsers['@TYPESCRIPT_ESLINT']
+ }]), {
+ code: `
+ class OptionalChaining extends React.Component {
+ constructor() {
+ this.state = { foo: 0 };
+ }
+ render() {
+ return
;
+ }
+ }`,
+ parser: parsers.BABEL_ESLINT
},
`class VariableDeclarationTest extends React.Component {
constructor() {
@@ -742,8 +764,60 @@ eslintTester.run('no-unused-state', rule, {
}
}`,
parser: parsers.BABEL_ESLINT
+ }, {
+ code: `
+ class Foo extends Component {
+ state = {
+ thisStateAliasProp,
+ thisStateAliasRestProp,
+ thisDestructStateAliasProp,
+ thisDestructStateAliasRestProp,
+ thisDestructStateDestructRestProp,
+ thisSetStateProp,
+ thisSetStateRestProp,
+ } as unknown
+
+ constructor() {
+ // other methods of defining state props
+ ((this as unknown).state as unknown) = { thisStateProp } as unknown;
+ ((this as unknown).setState as unknown)({ thisStateDestructProp } as unknown);
+ ((this as unknown).setState as unknown)(state => ({ thisDestructStateDestructProp } as unknown));
+ }
+
+ thisStateAlias() {
+ const state = (this as unknown).state as unknown;
+
+ (state as unknown).thisStateAliasProp as unknown;
+ const { ...thisStateAliasRest } = state as unknown;
+ (thisStateAliasRest as unknown).thisStateAliasRestProp as unknown;
+ }
+
+ thisDestructStateAlias() {
+ const { state } = this as unknown;
+
+ (state as unknown).thisDestructStateAliasProp as unknown;
+ const { ...thisDestructStateAliasRest } = state as unknown;
+ (thisDestructStateAliasRest as unknown).thisDestructStateAliasRestProp as unknown;
+ }
+
+ thisSetState() {
+ ((this as unknown).setState as unknown)(state => (state as unknown).thisSetStateProp as unknown);
+ ((this as unknown).setState as unknown)(({ ...thisSetStateRest }) => (thisSetStateRest as unknown).thisSetStateRestProp as unknown);
+ }
+
+ render() {
+ ((this as unknown).state as unknown).thisStateProp as unknown;
+ const { thisStateDestructProp } = (this as unknown).state as unknown;
+ const { state: { thisDestructStateDestructProp, ...thisDestructStateDestructRest } } = this as unknown;
+ (thisDestructStateDestructRest as unknown).thisDestructStateDestructRestProp as unknown;
+
+ return null;
+ }
+ }
+ `,
+ parser: parsers.TYPESCRIPT_ESLINT
}
- ],
+ ),
invalid: [
{
@@ -1119,6 +1193,70 @@ eslintTester.run('no-unused-state', rule, {
`,
parser: parsers.BABEL_ESLINT,
errors: getErrorMessages(['initial'])
+ }, {
+ code: `
+ class Foo extends Component {
+ state = {
+ thisStateAliasPropUnused,
+ thisStateAliasRestPropUnused,
+ thisDestructStateAliasPropUnused,
+ thisDestructStateAliasRestPropUnused,
+ thisDestructStateDestructRestPropUnused,
+ thisSetStatePropUnused,
+ thisSetStateRestPropUnused,
+ } as unknown
+
+ constructor() {
+ // other methods of defining state props
+ ((this as unknown).state as unknown) = { thisStatePropUnused } as unknown;
+ ((this as unknown).setState as unknown)({ thisStateDestructPropUnused } as unknown);
+ ((this as unknown).setState as unknown)(state => ({ thisDestructStateDestructPropUnused } as unknown));
+ }
+
+ thisStateAlias() {
+ const state = (this as unknown).state as unknown;
+
+ (state as unknown).thisStateAliasProp as unknown;
+ const { ...thisStateAliasRest } = state as unknown;
+ (thisStateAliasRest as unknown).thisStateAliasRestProp as unknown;
+ }
+
+ thisDestructStateAlias() {
+ const { state } = this as unknown;
+
+ (state as unknown).thisDestructStateAliasProp as unknown;
+ const { ...thisDestructStateAliasRest } = state as unknown;
+ (thisDestructStateAliasRest as unknown).thisDestructStateAliasRestProp as unknown;
+ }
+
+ thisSetState() {
+ ((this as unknown).setState as unknown)(state => (state as unknown).thisSetStateProp as unknown);
+ ((this as unknown).setState as unknown)(({ ...thisSetStateRest }) => (thisSetStateRest as unknown).thisSetStateRestProp as unknown);
+ }
+
+ render() {
+ ((this as unknown).state as unknown).thisStateProp as unknown;
+ const { thisStateDestructProp } = (this as unknown).state as unknown;
+ const { state: { thisDestructStateDestructProp, ...thisDestructStateDestructRest } } = this as unknown;
+ (thisDestructStateDestructRest as unknown).thisDestructStateDestructRestProp as unknown;
+
+ return null;
+ }
+ }
+ `,
+ parser: parsers.TYPESCRIPT_ESLINT,
+ errors: getErrorMessages([
+ 'thisStateAliasPropUnused',
+ 'thisStateAliasRestPropUnused',
+ 'thisDestructStateAliasPropUnused',
+ 'thisDestructStateAliasRestPropUnused',
+ 'thisDestructStateDestructRestPropUnused',
+ 'thisSetStatePropUnused',
+ 'thisSetStateRestPropUnused',
+ 'thisStatePropUnused',
+ 'thisStateDestructPropUnused',
+ 'thisDestructStateDestructPropUnused'
+ ])
}
]
});
diff --git a/tests/lib/rules/prefer-read-only-props.js b/tests/lib/rules/prefer-read-only-props.js
index d1b9b46f26..9445605c68 100644
--- a/tests/lib/rules/prefer-read-only-props.js
+++ b/tests/lib/rules/prefer-read-only-props.js
@@ -151,13 +151,24 @@ ruleTester.run('prefer-read-only-props', rule, {
parser: parsers.BABEL_ESLINT,
errors: [{
message: 'Prop \'name\' should be read-only.'
- }]
+ }],
+ output: `
+ type Props = {
+ +name: string,
+ }
+
+ class Hello extends React.Component
{
+ render () {
+ return Hello {this.props.name}
;
+ }
+ }
+ `
},
{
// Props.name is contravariant
code: `
type Props = {
- -name: string,
+ -name: string,
}
class Hello extends React.Component {
@@ -169,7 +180,18 @@ ruleTester.run('prefer-read-only-props', rule, {
parser: parsers.BABEL_ESLINT,
errors: [{
message: 'Prop \'name\' should be read-only.'
- }]
+ }],
+ output: `
+ type Props = {
+ +name: string,
+ }
+
+ class Hello extends React.Component {
+ render () {
+ return Hello {this.props.name}
;
+ }
+ }
+ `
},
{
code: `
@@ -186,7 +208,18 @@ ruleTester.run('prefer-read-only-props', rule, {
parser: parsers.BABEL_ESLINT,
errors: [{
message: 'Prop \'name\' should be read-only.'
- }]
+ }],
+ output: `
+ class Hello extends React.Component {
+ props: {
+ +name: string,
+ }
+
+ render () {
+ return Hello {this.props.name}
;
+ }
+ }
+ `
},
{
code: `
@@ -197,7 +230,12 @@ ruleTester.run('prefer-read-only-props', rule, {
parser: parsers.BABEL_ESLINT,
errors: [{
message: 'Prop \'name\' should be read-only.'
- }]
+ }],
+ output: `
+ function Hello(props: {+name: string}) {
+ return Hello {props.name}
;
+ }
+ `
},
{
code: `
@@ -208,7 +246,12 @@ ruleTester.run('prefer-read-only-props', rule, {
parser: parsers.BABEL_ESLINT,
errors: [{
message: 'Prop \'name\' should be read-only.'
- }]
+ }],
+ output: `
+ function Hello(props: {|+name: string|}) {
+ return Hello {props.name}
;
+ }
+ `
},
{
code: `
@@ -219,7 +262,12 @@ ruleTester.run('prefer-read-only-props', rule, {
parser: parsers.BABEL_ESLINT,
errors: [{
message: 'Prop \'name\' should be read-only.'
- }]
+ }],
+ output: `
+ function Hello({name}: {+name: string}) {
+ return Hello {props.name}
;
+ }
+ `
},
{
code: `
@@ -236,7 +284,16 @@ ruleTester.run('prefer-read-only-props', rule, {
message: 'Prop \'firstName\' should be read-only.'
}, {
message: 'Prop \'lastName\' should be read-only.'
- }]
+ }],
+ output: `
+ type PropsA = {+firstName: string};
+ type PropsB = {+lastName: string};
+ type Props = PropsA & PropsB;
+
+ function Hello({firstName, lastName}: Props) {
+ return Hello {firstName} {lastName}
;
+ }
+ `
},
{
code: `
@@ -247,7 +304,12 @@ ruleTester.run('prefer-read-only-props', rule, {
parser: parsers.BABEL_ESLINT,
errors: [{
message: 'Prop \'name\' should be read-only.'
- }]
+ }],
+ output: `
+ const Hello = (props: {+name: string}) => (
+ Hello {props.name}
+ );
+ `
}
]
});
diff --git a/tests/lib/rules/prefer-stateless-function.js b/tests/lib/rules/prefer-stateless-function.js
index e6a151f57b..7f7e41bb06 100644
--- a/tests/lib/rules/prefer-stateless-function.js
+++ b/tests/lib/rules/prefer-stateless-function.js
@@ -157,6 +157,18 @@ ruleTester.run('prefer-stateless-function', rule, {
}
}
`
+ }, {
+ // Issue 2187
+ code: `
+ class Foo extends React.Component {
+ constructor(props)
+
+ render() {
+ return {this.props.foo}
;
+ }
+ }
+ `,
+ parser: parsers.TYPESCRIPT_ESLINT
}, {
// Use this.bar
code: `
diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js
index 71714be846..e120d34f5f 100755
--- a/tests/lib/rules/prop-types.js
+++ b/tests/lib/rules/prop-types.js
@@ -1448,7 +1448,8 @@ ruleTester.run('prop-types', rule, {
' }',
'});'
].join('\n'),
- options: [{skipUndeclared: true}]
+ options: [{skipUndeclared: true}],
+ parser: parsers.BABEL_ESLINT
}, {
code: [
'class Hello extends React.Component {',
@@ -1632,6 +1633,34 @@ ruleTester.run('prop-types', rule, {
'}'
].join('\n'),
parser: parsers.BABEL_ESLINT
+ }, {
+ code: [
+ 'type OtherProps = {',
+ ' firstname: string,',
+ '};',
+ 'type Props = {',
+ ' ...OtherProps,',
+ ' lastname: string',
+ '};',
+ 'class Hello extends React.Component {',
+ ' props: Props;',
+ ' render () {',
+ ' return Hello {this.props.firstname}
;',
+ ' }',
+ '}'
+ ].join('\n'),
+ parser: parsers.BABEL_ESLINT
+ }, {
+ code: `
+ type FooProps = {
+ ...any,
+ ...42,
+ }
+ function Foo(props: FooProps) {
+ return ;
+ }
+ `,
+ parser: parsers.BABEL_ESLINT
}, {
code: [
'type Person = {',
@@ -2065,6 +2094,17 @@ ruleTester.run('prop-types', rule, {
};
`
},
+ {
+ code: `
+ class Foo extends React.Component {
+ bar() {
+ this.setState((state, props) => {
+ function f(_, {aaaaaaa}) {}
+ });
+ }
+ }
+ `
+ },
{
code: `
class Foo extends React.Component {
@@ -2324,6 +2364,30 @@ ruleTester.run('prop-types', rule, {
`,
parser: parsers.BABEL_ESLINT
},
+ {
+ // issue #2138
+ code: `
+ type UsedProps = {|
+ usedProp: number,
+ |};
+
+ type UnusedProps = {|
+ unusedProp: number,
+ |};
+
+ type Props = {| ...UsedProps, ...UnusedProps |};
+
+ function MyComponent({ usedProp }: Props) {
+ return {usedProp}
;
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ errors: [{
+ message: "'notOne' is missing in props validation",
+ line: 8,
+ column: 34
+ }]
+ },
{
// issue #1259
code: `
@@ -2412,6 +2476,19 @@ ruleTester.run('prop-types', rule, {
pragma: 'Foo'
}
}
+ },
+ {
+ code: `
+ const Foo = ({length, ordering}) => (
+ length > 0 && (
+
+ )
+ );
+ Foo.propTypes = {
+ length: PropTypes.number,
+ ordering: PropTypes.array
+ };
+ `
}
],
@@ -4717,6 +4794,30 @@ ruleTester.run('prop-types', rule, {
message: '\'initialValues\' is missing in props validation'
}]
},
+ {
+ // issue #2138
+ code: `
+ type UsedProps = {|
+ usedProp: number,
+ |};
+
+ type UnusedProps = {|
+ unusedProp: number,
+ |};
+
+ type Props = {| ...UsedProps, ...UnusedProps |};
+
+ function MyComponent({ usedProp, notOne }: Props) {
+ return {usedProp}
;
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ errors: [{
+ message: "'notOne' is missing in props validation",
+ line: 12,
+ column: 42
+ }]
+ },
{
// issue #2298
code: `
@@ -4797,6 +4898,42 @@ ruleTester.run('prop-types', rule, {
errors: [{
message: '\'text\' is missing in props validation'
}]
+ },
+ {
+ code: `
+ function Foo({
+ foo: {
+ bar: foo,
+ baz
+ },
+ }) {
+ return {foo.reduce(() => 5)}
;
+ }
+
+ Foo.propTypes = {
+ foo: PropTypes.shape({
+ bar: PropTypes.arrayOf(PropTypes.string).isRequired,
+ }).isRequired,
+ };
+ `,
+ errors: [{
+ message: '\'foo.baz\' is missing in props validation'
+ }]
+ },
+ {
+ code: `
+ const Foo = ({length, ordering}) => (
+ length > 0 && (
+
+ )
+ );
+ `,
+ errors: [{
+ message: '\'length\' is missing in props validation'
+ },
+ {
+ message: '\'ordering\' is missing in props validation'
+ }]
}
]
});
diff --git a/tests/lib/rules/react-in-jsx-scope.js b/tests/lib/rules/react-in-jsx-scope.js
index 4371074d48..47f206ddf3 100644
--- a/tests/lib/rules/react-in-jsx-scope.js
+++ b/tests/lib/rules/react-in-jsx-scope.js
@@ -41,7 +41,10 @@ ruleTester.run('react-in-jsx-scope', rule, {
{code: 'var React; ;'},
{code: 'var React, App, a=1; ;'},
{code: 'var React, App, a=1; function elem() { return ; }'},
- {code: 'var React, App; ;'},
+ {
+ code: 'var React, App; ;',
+ parser: parsers.BABEL_ESLINT
+ },
{code: '/** @jsx Foo */ var Foo, App; ;'},
{code: '/** @jsx Foo.Bar */ var Foo, App; ;'},
{
diff --git a/tests/lib/rules/require-default-props.js b/tests/lib/rules/require-default-props.js
index fa55087d8d..409f4a6250 100644
--- a/tests/lib/rules/require-default-props.js
+++ b/tests/lib/rules/require-default-props.js
@@ -32,7 +32,7 @@ ruleTester.run('require-default-props', rule, {
valid: [
//
- // stateless components
+ // stateless components as function declarations
{
code: [
'function MyStatelessComponent({ foo, bar }) {',
@@ -152,6 +152,207 @@ ruleTester.run('require-default-props', rule, {
'MyStatelessComponent.defaultProps = defaults;'
].join('\n')
},
+ {
+ code: [
+ 'function MyStatelessComponent({ foo, bar }) {',
+ ' return {foo}{bar}
;',
+ '}',
+ 'MyStatelessComponent.propTypes = {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ '};'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}]
+ },
+ {
+ code: [
+ 'function MyStatelessComponent({ foo = "test", bar }) {',
+ ' return {foo}{bar}
;',
+ '}',
+ 'MyStatelessComponent.propTypes = {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ '};'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}]
+ },
+ {
+ code: [
+ 'function MyStatelessComponent({ foo = "test", bar }) {',
+ ' return {foo}{bar}
;',
+ '}',
+ 'MyStatelessComponent.propTypes = {',
+ ' foo: PropTypes.string,',
+ '};'
+ ].join('\n'),
+ options: [{forbidDefaultForRequired: true, ignoreFunctionalComponents: true}]
+ },
+ {
+ code: [
+ 'export function MyStatelessComponent({ foo, bar }) {',
+ ' return {foo}{bar}
;',
+ '}',
+ 'MyStatelessComponent.propTypes = {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ '};'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}],
+ parser: parsers.BABEL_ESLINT
+ },
+ {
+ code: [
+ 'export function MyStatelessComponent({ foo, bar }) {',
+ ' return {foo}{bar}
;',
+ '}',
+ 'MyStatelessComponent.propTypes = {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ '};'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}],
+ parser: parsers.TYPESCRIPT_ESLINT
+ },
+ {
+ code: [
+ 'export default function MyStatelessComponent({ foo, bar }) {',
+ ' return {foo}{bar}
;',
+ '}',
+ 'MyStatelessComponent.propTypes = {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ '};'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}],
+ parser: parsers.BABEL_ESLINT
+ },
+ {
+ code: [
+ 'export default function MyStatelessComponent({ foo, bar }) {',
+ ' return {foo}{bar}
;',
+ '}',
+ 'MyStatelessComponent.propTypes = {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ '};'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}],
+ parser: parsers.TYPESCRIPT_ESLINT
+ },
+
+ //
+ // stateless components as function expressions
+ {
+ code: `
+ import PropTypes from 'prop-types';
+ import React from 'react';
+
+ const MyComponent = function({ foo, bar }) {
+ return {foo}{bar}
;
+ };
+
+ MyComponent.propTypes = {
+ foo: PropTypes.string,
+ bar: PropTypes.string.isRequired
+ };
+
+ export default MyComponent;
+ `,
+ options: [{ignoreFunctionalComponents: true}]
+ },
+ {
+ code: `
+ import PropTypes from 'prop-types';
+ import React from 'react';
+
+ export const MyComponent = function({ foo, bar }) {
+ return {foo}{bar}
;
+ };
+
+ MyComponent.propTypes = {
+ foo: PropTypes.string,
+ bar: PropTypes.string.isRequired
+ };
+ `,
+ options: [{ignoreFunctionalComponents: true}],
+ parser: parsers.BABEL_ESLINT
+ },
+ {
+ code: `
+ import PropTypes from 'prop-types';
+ import React from 'react';
+
+ export const MyComponent = function({ foo, bar }) {
+ return {foo}{bar}
;
+ };
+
+ MyComponent.propTypes = {
+ foo: PropTypes.string,
+ bar: PropTypes.string.isRequired
+ };
+ `,
+ options: [{ignoreFunctionalComponents: true}],
+ parser: parsers.TYPESCRIPT_ESLINT
+ },
+
+ //
+ // stateless components as arrow function expressions
+ {
+ code: `
+ import PropTypes from 'prop-types';
+ import React from 'react';
+
+ const MyComponent = ({ foo, bar }) => {
+ return {foo}{bar}
;
+ };
+
+ MyComponent.propTypes = {
+ foo: PropTypes.string,
+ bar: PropTypes.string.isRequired
+ };
+
+ export default MyComponent;
+ `,
+ options: [{ignoreFunctionalComponents: true}]
+ },
+ {
+ code: `
+ import PropTypes from 'prop-types';
+ import React from 'react';
+
+ export const MyComponent = ({ foo, bar }) => {
+ return {foo}{bar}
;
+ };
+
+ MyComponent.propTypes = {
+ foo: PropTypes.string,
+ bar: PropTypes.string.isRequired
+ };
+
+ export default MyComponent;
+ `,
+ options: [{ignoreFunctionalComponents: true}],
+ parser: parsers.BABEL_ESLINT
+ },
+ {
+ code: `
+ import PropTypes from 'prop-types';
+ import React from 'react';
+
+ export const MyComponent = ({ foo, bar }) => {
+ return {foo}{bar}
;
+ };
+
+ MyComponent.propTypes = {
+ foo: PropTypes.string,
+ bar: PropTypes.string.isRequired
+ };
+
+ export default MyComponent;
+ `,
+ options: [{ignoreFunctionalComponents: true}],
+ parser: parsers.TYPESCRIPT_ESLINT
+ },
//
// createReactClass components
@@ -214,6 +415,26 @@ ruleTester.run('require-default-props', rule, {
'});'
].join('\n')
},
+ {
+ code: [
+ 'var Greeting = createReactClass({',
+ ' render: function() {',
+ ' return Hello {this.props.foo} {this.props.bar}
;',
+ ' },',
+ ' propTypes: {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string',
+ ' },',
+ ' getDefaultProps: function() {',
+ ' return {',
+ ' foo: "foo",',
+ ' bar: "bar"',
+ ' };',
+ ' }',
+ '});'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}]
+ },
//
// ES6 class component
@@ -314,6 +535,25 @@ ruleTester.run('require-default-props', rule, {
'Greeting.defaultProps.foo = "foo";'
].join('\n')
},
+ {
+ code: [
+ 'class Greeting extends React.Component {',
+ ' render() {',
+ ' return (',
+ ' Hello, {this.props.foo} {this.props.bar}
',
+ ' );',
+ ' }',
+ '}',
+ 'Greeting.propTypes = {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ '};',
+ 'Greeting.defaultProps = {',
+ ' foo: "foo"',
+ '};'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}]
+ },
//
// edge cases
@@ -514,7 +754,8 @@ ruleTester.run('require-default-props', rule, {
' ...defaults,',
' bar: "bar"',
'};'
- ].join('\n')
+ ].join('\n'),
+ parser: parsers.BABEL_ESLINT
},
//
@@ -1015,6 +1256,25 @@ ruleTester.run('require-default-props', rule, {
column: 5
}]
},
+ {
+ code: [
+ 'var Greeting = createReactClass({',
+ ' render: function() {',
+ ' return Hello {this.props.foo} {this.props.bar}
;',
+ ' },',
+ ' propTypes: {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ ' }',
+ '});'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}],
+ errors: [{
+ message: 'propType "foo" is not required, but has no corresponding defaultProps declaration.',
+ line: 6,
+ column: 5
+ }]
+ },
{
code: [
'var Greeting = createReactClass({',
@@ -1061,6 +1321,27 @@ ruleTester.run('require-default-props', rule, {
column: 3
}]
},
+ {
+ code: [
+ 'class Greeting extends React.Component {',
+ ' render() {',
+ ' return (',
+ ' Hello, {this.props.foo} {this.props.bar}
',
+ ' );',
+ ' }',
+ '}',
+ 'Greeting.propTypes = {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ '};'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}],
+ errors: [{
+ message: 'propType "foo" is not required, but has no corresponding defaultProps declaration.',
+ line: 9,
+ column: 3
+ }]
+ },
{
code: [
'class Greeting extends React.Component {',
@@ -1214,6 +1495,26 @@ ruleTester.run('require-default-props', rule, {
column: 7
}]
},
+ {
+ code: [
+ 'class Hello extends React.Component {',
+ ' static get propTypes() {',
+ ' return {',
+ ' name: PropTypes.string',
+ ' };',
+ ' }',
+ ' render() {',
+ ' return Hello {this.props.name}
;',
+ ' }',
+ '}'
+ ].join('\n'),
+ options: [{ignoreFunctionalComponents: true}],
+ errors: [{
+ message: 'propType "name" is not required, but has no corresponding defaultProps declaration.',
+ line: 4,
+ column: 7
+ }]
+ },
{
code: [
'class Hello extends React.Component {',
@@ -1311,6 +1612,28 @@ ruleTester.run('require-default-props', rule, {
column: 5
}]
},
+ {
+ code: [
+ 'class Greeting extends React.Component {',
+ ' render() {',
+ ' return (',
+ ' Hello, {this.props.foo} {this.props.bar}
',
+ ' );',
+ ' }',
+ ' static propTypes = {',
+ ' foo: PropTypes.string,',
+ ' bar: PropTypes.string.isRequired',
+ ' };',
+ '}'
+ ].join('\n'),
+ parser: parsers.BABEL_ESLINT,
+ options: [{ignoreFunctionalComponents: true}],
+ errors: [{
+ message: 'propType "foo" is not required, but has no corresponding defaultProps declaration.',
+ line: 8,
+ column: 5
+ }]
+ },
{
code: [
'class Greeting extends React.Component {',
@@ -1789,23 +2112,6 @@ ruleTester.run('require-default-props', rule, {
column: 47
}]
},
- {
- code: [
- 'type Props = {',
- ' foo?: string',
- '};',
-
- 'function Hello(props: Props) {',
- ' return Hello {props.foo}
;',
- '}'
- ].join('\n'),
- parser: parsers.BABEL_ESLINT,
- errors: [{
- message: 'propType "foo" is not required, but has no corresponding defaultProps declaration.',
- line: 2,
- column: 3
- }]
- },
{
code: [
'type Props = {',
@@ -2225,6 +2531,20 @@ ruleTester.run('require-default-props', rule, {
errors: [{
message: 'propType "usedProp" is not required, but has no corresponding defaultProps declaration.'
}]
+ },
+ {
+ code: `
+ Foo.propTypes = {
+ a: PropTypes.string,
+ }
+
+ export default function Foo(props) {
+ return {props.a}
+ };
+ `,
+ errors: [{
+ message: 'propType "a" is not required, but has no corresponding defaultProps declaration.'
+ }]
}
]
});
diff --git a/tests/lib/rules/require-optimization.js b/tests/lib/rules/require-optimization.js
index ea5da36295..01e9ca0bc8 100644
--- a/tests/lib/rules/require-optimization.js
+++ b/tests/lib/rules/require-optimization.js
@@ -118,6 +118,23 @@ ruleTester.run('react-require-optimization', rule, {
code: `
const obj = { prop: [,,,,,] }
`
+ }, {
+ code: `
+ import React from "react";
+ class YourComponent extends React.Component {
+ handleClick = () => {}
+ shouldComponentUpdate(){
+ return true;
+ }
+ render() {
+ return 123
+ }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ errors: [{
+ message: MESSAGE
+ }]
}],
invalid: [{
@@ -142,6 +159,20 @@ ruleTester.run('react-require-optimization', rule, {
errors: [{
message: MESSAGE
}]
+ }, {
+ code: `
+ import React from "react";
+ class YourComponent extends React.Component {
+ handleClick = () => {}
+ render() {
+ return 123
+ }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ errors: [{
+ message: MESSAGE
+ }]
}, {
code: `
import React, {Component} from "react";
diff --git a/tests/lib/rules/require-render-return.js b/tests/lib/rules/require-render-return.js
index 07488c9b88..fa07a94c74 100644
--- a/tests/lib/rules/require-render-return.js
+++ b/tests/lib/rules/require-render-return.js
@@ -150,7 +150,7 @@ ruleTester.run('require-render-return', rule, {
});
`,
errors: [{
- message: 'Your render method should have return statement',
+ message: 'Your render method should have a return statement',
line: 4
}]
}, {
@@ -161,7 +161,7 @@ ruleTester.run('require-render-return', rule, {
}
`,
errors: [{
- message: 'Your render method should have return statement'
+ message: 'Your render method should have a return statement'
}]
}, {
// Missing return (but one is present in a sub-function)
@@ -175,7 +175,7 @@ ruleTester.run('require-render-return', rule, {
}
`,
errors: [{
- message: 'Your render method should have return statement',
+ message: 'Your render method should have a return statement',
line: 3
}]
}, {
@@ -189,7 +189,7 @@ ruleTester.run('require-render-return', rule, {
`,
parser: parsers.BABEL_ESLINT,
errors: [{
- message: 'Your render method should have return statement',
+ message: 'Your render method should have a return statement',
type: 'ClassProperty'
}]
}]
diff --git a/tests/lib/rules/self-closing-comp.js b/tests/lib/rules/self-closing-comp.js
index 57321bb405..ec36323d74 100644
--- a/tests/lib/rules/self-closing-comp.js
+++ b/tests/lib/rules/self-closing-comp.js
@@ -30,30 +30,52 @@ ruleTester.run('self-closing-comp', rule, {
valid: [
{
code: 'var HelloJohn = ;'
+ }, {
+ code: 'var HelloJohn = ;'
}, {
code: 'var Profile =
;'
+ }, {
+ code: 'var Profile =
;'
}, {
code: `
`
+ }, {
+ code: `
+
+
+
+ `
}, {
code: 'var HelloJohn = ;'
+ }, {
+ code: 'var HelloJohn = ;'
}, {
code: 'var HelloJohn = ;'
+ }, {
+ code: 'var HelloJohn = ;'
}, {
code: 'var HelloJohn =
;'
}, {
code: 'var HelloJohn = {\' \'}
;'
}, {
code: 'var HelloJohn = ;'
+ }, {
+ code: 'var HelloJohn = ;'
}, {
code: 'var HelloJohn = ;',
options: []
+ }, {
+ code: 'var HelloJohn = ;',
+ options: []
}, {
code: 'var Profile =
;',
options: []
+ }, {
+ code: 'var Profile =
;',
+ options: []
}, {
code: `
@@ -61,6 +83,13 @@ ruleTester.run('self-closing-comp', rule, {
`,
options: []
+ }, {
+ code: `
+
+
+
+ `,
+ options: []
}, {
code: 'var HelloJohn =
;',
options: []
@@ -76,15 +105,27 @@ ruleTester.run('self-closing-comp', rule, {
}, {
code: 'var HelloJohn = ;',
options: []
+ }, {
+ code: 'var HelloJohn = ;',
+ options: []
}, {
code: 'var HelloJohn = ;',
options: [{component: false}]
+ }, {
+ code: 'var HelloJohn = ;',
+ options: [{component: false}]
}, {
code: 'var HelloJohn = \n;',
options: [{component: false}]
+ }, {
+ code: 'var HelloJohn = \n;',
+ options: [{component: false}]
}, {
code: 'var HelloJohn = ;',
options: [{component: false}]
+ }, {
+ code: 'var HelloJohn = ;',
+ options: [{component: false}]
}, {
code: 'var contentContainer = ;',
options: [{html: true}]
@@ -121,12 +162,24 @@ ruleTester.run('self-closing-comp', rule, {
errors: [{
message: 'Empty components are self-closing'
}]
+ }, {
+ code: 'var CompoundHelloJohn = ;',
+ output: 'var CompoundHelloJohn = ;',
+ errors: [{
+ message: 'Empty components are self-closing'
+ }]
}, {
code: 'var HelloJohn = \n;',
output: 'var HelloJohn = ;',
errors: [{
message: 'Empty components are self-closing'
}]
+ }, {
+ code: 'var HelloJohn = \n;',
+ output: 'var HelloJohn = ;',
+ errors: [{
+ message: 'Empty components are self-closing'
+ }]
}, {
code: 'var HelloJohn = ;',
output: 'var HelloJohn = ;',
@@ -134,6 +187,13 @@ ruleTester.run('self-closing-comp', rule, {
errors: [{
message: 'Empty components are self-closing'
}]
+ }, {
+ code: 'var HelloJohn = ;',
+ output: 'var HelloJohn = ;',
+ options: [],
+ errors: [{
+ message: 'Empty components are self-closing'
+ }]
}, {
code: 'var HelloJohn = \n;',
output: 'var HelloJohn = ;',
@@ -141,6 +201,13 @@ ruleTester.run('self-closing-comp', rule, {
errors: [{
message: 'Empty components are self-closing'
}]
+ }, {
+ code: 'var HelloJohn = \n;',
+ output: 'var HelloJohn = ;',
+ options: [],
+ errors: [{
+ message: 'Empty components are self-closing'
+ }]
}, {
code: 'var contentContainer = ;',
output: 'var contentContainer = ;',
diff --git a/tests/lib/rules/sort-comp.js b/tests/lib/rules/sort-comp.js
index 7c67bcb4a8..d30bb25f48 100644
--- a/tests/lib/rules/sort-comp.js
+++ b/tests/lib/rules/sort-comp.js
@@ -506,6 +506,129 @@ ruleTester.run('sort-comp', rule, {
'everything-else'
]
}]
+ }, {
+ code: `
+ class MyComponent extends React.Component {
+ static foo;
+ static getDerivedStateFromProps() {}
+
+ render() {
+ return null;
+ }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ options: [{
+ order: [
+ 'static-variables',
+ 'static-methods'
+ ]
+ }]
+ }, {
+ code: `
+ class MyComponent extends React.Component {
+ static getDerivedStateFromProps() {}
+ static foo = 'some-str';
+
+ render() {
+ return null;
+ }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ options: [{
+ order: [
+ 'static-methods',
+ 'static-variables'
+ ]
+ }]
+ }, {
+ code: `
+ class MyComponent extends React.Component {
+ foo = {};
+ static bar = 0;
+ static getDerivedStateFromProps() {}
+
+ render() {
+ return null;
+ }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ options: [{
+ order: [
+ 'instance-variables',
+ 'static-variables',
+ 'static-methods'
+ ]
+ }]
+ }, {
+ code: `
+ class MyComponent extends React.Component {
+ static bar = 1;
+ foo = {};
+ static getDerivedStateFromProps() {}
+
+ render() {
+ return null;
+ }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ options: [{
+ order: [
+ 'static-variables',
+ 'instance-variables',
+ 'static-methods'
+ ]
+ }]
+ }, {
+ code: `
+ class MyComponent extends React.Component {
+ static getDerivedStateFromProps() {}
+ render() {
+ return null;
+ }
+ static bar;
+ foo = {};
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ options: [{
+ order: [
+ 'static-methods',
+ 'render',
+ 'static-variables',
+ 'instance-variables'
+ ]
+ }]
+ }, {
+ code: `
+ class MyComponent extends React.Component {
+ static foo = 1;
+ bar;
+
+ constructor() {
+ super(props);
+
+ this.state = {};
+ }
+
+ render() {
+ return null;
+ }
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ options: [{
+ order: [
+ 'static-variables',
+ 'instance-variables',
+ 'constructor',
+ 'everything-else',
+ 'render'
+ ]
+ }]
}],
invalid: [{
@@ -790,5 +913,66 @@ ruleTester.run('sort-comp', rule, {
'render'
]
}]
+ }, {
+ code: `
+ class MyComponent extends React.Component {
+ static getDerivedStateFromProps() {}
+ static foo;
+
+ render() {
+ return null;
+ }
+ }
+ `,
+ errors: [{message: 'getDerivedStateFromProps should be placed after foo'}],
+ parser: parsers.BABEL_ESLINT,
+ options: [{
+ order: [
+ 'static-variables',
+ 'static-methods'
+ ]
+ }]
+ }, {
+ code: `
+ class MyComponent extends React.Component {
+ static foo;
+ bar = 'some-str'
+ static getDerivedStateFromProps() {}
+
+ render() {
+ return null;
+ }
+ }
+ `,
+ errors: [{message: 'foo should be placed after bar'}],
+ parser: parsers.BABEL_ESLINT,
+ options: [{
+ order: [
+ 'instance-variables',
+ 'static-variables',
+ 'static-methods'
+ ]
+ }]
+ }, {
+ code: `
+ class MyComponent extends React.Component {
+ static getDerivedStateFromProps() {}
+ static bar;
+ render() {
+ return null;
+ }
+ foo = {};
+ }
+ `,
+ parser: parsers.BABEL_ESLINT,
+ errors: [{message: 'bar should be placed after render'}],
+ options: [{
+ order: [
+ 'static-methods',
+ 'render',
+ 'static-variables',
+ 'instance-variables'
+ ]
+ }]
}]
});
diff --git a/tests/lib/rules/sort-prop-types.js b/tests/lib/rules/sort-prop-types.js
index 6326a7d89d..65a529d589 100644
--- a/tests/lib/rules/sort-prop-types.js
+++ b/tests/lib/rules/sort-prop-types.js
@@ -486,18 +486,52 @@ ruleTester.run('sort-prop-types', rule, {
line: 4,
column: 5,
type: 'Property'
- }],
- output: [
+ }]
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
+ }, {
+ code: [
'var First = createReactClass({',
' propTypes: {',
- ' a: PropTypes.any,',
- ' z: PropTypes.string',
+ ' /* z */',
+ ' z: PropTypes.string,',
+ ' /* a */',
+ ' a: PropTypes.any',
' },',
' render: function() {',
' return ;',
' }',
'});'
- ].join('\n')
+ ].join('\n'),
+ errors: [{
+ message: ERROR_MESSAGE,
+ line: 6,
+ column: 5,
+ type: 'Property'
+ }]
+ // Disabled test for comments -- fails
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' /* a */',
+ // ' a: PropTypes.any,',
+ // ' /* z */',
+ // ' z: PropTypes.string',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'var First = createReactClass({',
@@ -515,18 +549,18 @@ ruleTester.run('sort-prop-types', rule, {
line: 4,
column: 5,
type: 'Property'
- }],
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' Z: PropTypes.any,',
- ' z: PropTypes.any',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ }]
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' Z: PropTypes.any,',
+ // ' z: PropTypes.any',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'var First = createReactClass({',
@@ -547,18 +581,18 @@ ruleTester.run('sort-prop-types', rule, {
line: 4,
column: 5,
type: 'Property'
- }],
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' a: PropTypes.any,',
- ' Z: PropTypes.any',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ }]
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' a: PropTypes.any,',
+ // ' Z: PropTypes.any',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'var First = createReactClass({',
@@ -573,20 +607,20 @@ ruleTester.run('sort-prop-types', rule, {
' }',
'});'
].join('\n'),
- errors: 2,
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' A: PropTypes.any,',
- ' Z: PropTypes.string,',
- ' a: PropTypes.any,',
- ' z: PropTypes.string',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ errors: 2
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' A: PropTypes.any,',
+ // ' Z: PropTypes.string,',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'var First = createReactClass({',
@@ -608,27 +642,27 @@ ruleTester.run('sort-prop-types', rule, {
' }',
'});'
].join('\n'),
- errors: 2,
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' Zz: PropTypes.string,',
- ' a: PropTypes.any',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});',
- 'var Second = createReactClass({',
- ' propTypes: {',
- ' ZZ: PropTypes.string,',
- ' aAA: PropTypes.any',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ errors: 2
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' Zz: PropTypes.string,',
+ // ' a: PropTypes.any',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});',
+ // 'var Second = createReactClass({',
+ // ' propTypes: {',
+ // ' ZZ: PropTypes.string,',
+ // ' aAA: PropTypes.any',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'class First extends React.Component {',
@@ -650,27 +684,27 @@ ruleTester.run('sort-prop-types', rule, {
' ZZ: PropTypes.string',
'};'
].join('\n'),
- errors: 2,
- output: [
- 'class First extends React.Component {',
- ' render() {',
- ' return ;',
- ' }',
- '}',
- 'First.propTypes = {',
- ' bb: PropTypes.string,',
- ' yy: PropTypes.any',
- '};',
- 'class Second extends React.Component {',
- ' render() {',
- ' return ;',
- ' }',
- '}',
- 'Second.propTypes = {',
- ' ZZ: PropTypes.string,',
- ' aAA: PropTypes.any',
- '};'
- ].join('\n')
+ errors: 2
+ // output: [
+ // 'class First extends React.Component {',
+ // ' render() {',
+ // ' return ;',
+ // ' }',
+ // '}',
+ // 'First.propTypes = {',
+ // ' bb: PropTypes.string,',
+ // ' yy: PropTypes.any',
+ // '};',
+ // 'class Second extends React.Component {',
+ // ' render() {',
+ // ' return ;',
+ // ' }',
+ // '}',
+ // 'Second.propTypes = {',
+ // ' ZZ: PropTypes.string,',
+ // ' aAA: PropTypes.any',
+ // '};'
+ // ].join('\n')
}, {
code: [
'class Component extends React.Component {',
@@ -685,19 +719,19 @@ ruleTester.run('sort-prop-types', rule, {
'}'
].join('\n'),
parser: parsers.BABEL_ESLINT,
- errors: 2,
- output: [
- 'class Component extends React.Component {',
- ' static propTypes = {',
- ' a: PropTypes.any,',
- ' y: PropTypes.any,',
- ' z: PropTypes.any',
- ' };',
- ' render() {',
- ' return ;',
- ' }',
- '}'
- ].join('\n')
+ errors: 2
+ // output: [
+ // 'class Component extends React.Component {',
+ // ' static propTypes = {',
+ // ' a: PropTypes.any,',
+ // ' y: PropTypes.any,',
+ // ' z: PropTypes.any',
+ // ' };',
+ // ' render() {',
+ // ' return ;',
+ // ' }',
+ // '}'
+ // ].join('\n')
}, {
code: [
'class Component extends React.Component {',
@@ -715,19 +749,19 @@ ruleTester.run('sort-prop-types', rule, {
settings: {
propWrapperFunctions: ['forbidExtraProps']
},
- errors: 2,
- output: [
- 'class Component extends React.Component {',
- ' static propTypes = forbidExtraProps({',
- ' a: PropTypes.any,',
- ' y: PropTypes.any,',
- ' z: PropTypes.any',
- ' });',
- ' render() {',
- ' return ;',
- ' }',
- '}'
- ].join('\n')
+ errors: 2
+ // output: [
+ // 'class Component extends React.Component {',
+ // ' static propTypes = forbidExtraProps({',
+ // ' a: PropTypes.any,',
+ // ' y: PropTypes.any,',
+ // ' z: PropTypes.any',
+ // ' });',
+ // ' render() {',
+ // ' return ;',
+ // ' }',
+ // '}'
+ // ].join('\n')
}, {
code: [
'var First = createReactClass({',
@@ -750,20 +784,20 @@ ruleTester.run('sort-prop-types', rule, {
line: 6,
column: 5,
type: 'Property'
- }],
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' a: PropTypes.any,',
- ' z: PropTypes.string,',
- ' onBar: PropTypes.func,',
- ' onFoo: PropTypes.func',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ }]
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string,',
+ // ' onBar: PropTypes.func,',
+ // ' onFoo: PropTypes.func',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'class Component extends React.Component {',
@@ -787,20 +821,20 @@ ruleTester.run('sort-prop-types', rule, {
line: 6,
column: 5,
type: 'Property'
- }],
- output: [
- 'class Component extends React.Component {',
- ' static propTypes = {',
- ' a: PropTypes.any,',
- ' z: PropTypes.string,',
- ' onBar: PropTypes.func,',
- ' onFoo: PropTypes.func',
- ' };',
- ' render() {',
- ' return ;',
- ' }',
- '}'
- ].join('\n')
+ }]
+ // output: [
+ // 'class Component extends React.Component {',
+ // ' static propTypes = {',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string,',
+ // ' onBar: PropTypes.func,',
+ // ' onFoo: PropTypes.func',
+ // ' };',
+ // ' render() {',
+ // ' return ;',
+ // ' }',
+ // '}'
+ // ].join('\n')
}, {
code: [
'class First extends React.Component {',
@@ -823,20 +857,20 @@ ruleTester.run('sort-prop-types', rule, {
line: 10,
column: 5,
type: 'Property'
- }],
- output: [
- 'class First extends React.Component {',
- ' render() {',
- ' return ;',
- ' }',
- '}',
- 'First.propTypes = {',
- ' a: PropTypes.any,',
- ' z: PropTypes.string,',
- ' onBar: PropTypes.func,',
- ' onFoo: PropTypes.func',
- '};'
- ].join('\n')
+ }]
+ // output: [
+ // 'class First extends React.Component {',
+ // ' render() {',
+ // ' return ;',
+ // ' }',
+ // '}',
+ // 'First.propTypes = {',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string,',
+ // ' onBar: PropTypes.func,',
+ // ' onFoo: PropTypes.func',
+ // '};'
+ // ].join('\n')
}, {
code: [
'class First extends React.Component {',
@@ -862,20 +896,20 @@ ruleTester.run('sort-prop-types', rule, {
line: 10,
column: 5,
type: 'Property'
- }],
- output: [
- 'class First extends React.Component {',
- ' render() {',
- ' return ;',
- ' }',
- '}',
- 'First.propTypes = forbidExtraProps({',
- ' a: PropTypes.any,',
- ' z: PropTypes.string,',
- ' onBar: PropTypes.func,',
- ' onFoo: PropTypes.func',
- '});'
- ].join('\n')
+ }]
+ // output: [
+ // 'class First extends React.Component {',
+ // ' render() {',
+ // ' return ;',
+ // ' }',
+ // '}',
+ // 'First.propTypes = forbidExtraProps({',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string,',
+ // ' onBar: PropTypes.func,',
+ // ' onFoo: PropTypes.func',
+ // '});'
+ // ].join('\n')
}, {
code: [
'const First = (props) => ;',
@@ -893,15 +927,15 @@ ruleTester.run('sort-prop-types', rule, {
line: 4,
column: 5,
type: 'Property'
- }],
- output: [
- 'const First = (props) => ;',
- 'const propTypes = {',
- ' a: PropTypes.any,',
- ' z: PropTypes.string,',
- '};',
- 'First.propTypes = forbidExtraProps(propTypes);'
- ].join('\n')
+ }]
+ // output: [
+ // 'const First = (props) => ;',
+ // 'const propTypes = {',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string,',
+ // '};',
+ // 'First.propTypes = forbidExtraProps(propTypes);'
+ // ].join('\n')
}, {
code: [
'const First = (props) => ;',
@@ -919,15 +953,15 @@ ruleTester.run('sort-prop-types', rule, {
line: 4,
column: 5,
type: 'Property'
- }],
- output: [
- 'const First = (props) => ;',
- 'const propTypes = {',
- ' a: PropTypes.any,',
- ' z: PropTypes.string,',
- '};',
- 'First.propTypes = propTypes;'
- ].join('\n')
+ }]
+ // output: [
+ // 'const First = (props) => ;',
+ // 'const propTypes = {',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string,',
+ // '};',
+ // 'First.propTypes = propTypes;'
+ // ].join('\n')
}, {
code: [
'var First = createReactClass({',
@@ -950,20 +984,20 @@ ruleTester.run('sort-prop-types', rule, {
line: 5,
column: 5,
type: 'Property'
- }],
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' a: PropTypes.any,',
- ' z: PropTypes.string,',
- ' onBar: PropTypes.func,',
- ' onFoo: PropTypes.func',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ }]
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string,',
+ // ' onBar: PropTypes.func,',
+ // ' onFoo: PropTypes.func',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'var First = createReactClass({',
@@ -985,19 +1019,19 @@ ruleTester.run('sort-prop-types', rule, {
line: 4,
column: 5,
type: 'Property'
- }],
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' barRequired: PropTypes.string.isRequired,',
- ' fooRequired: PropTypes.string.isRequired,',
- ' a: PropTypes.any',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ }]
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' barRequired: PropTypes.string.isRequired,',
+ // ' fooRequired: PropTypes.string.isRequired,',
+ // ' a: PropTypes.any',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'var First = createReactClass({',
@@ -1019,19 +1053,19 @@ ruleTester.run('sort-prop-types', rule, {
line: 4,
column: 5,
type: 'Property'
- }],
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' barRequired: PropTypes.string.isRequired,',
- ' a: PropTypes.any,',
- ' onFoo: PropTypes.func',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ }]
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' barRequired: PropTypes.string.isRequired,',
+ // ' a: PropTypes.any,',
+ // ' onFoo: PropTypes.func',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'export default class ClassWithSpreadInPropTypes extends BaseClass {',
@@ -1049,17 +1083,17 @@ ruleTester.run('sort-prop-types', rule, {
line: 6,
column: 5,
type: 'Property'
- }],
- output: [
- 'export default class ClassWithSpreadInPropTypes extends BaseClass {',
- ' static propTypes = {',
- ' b: PropTypes.string,',
- ' ...a.propTypes,',
- ' c: PropTypes.string,',
- ' d: PropTypes.string',
- ' }',
- '}'
- ].join('\n')
+ }]
+ // output: [
+ // 'export default class ClassWithSpreadInPropTypes extends BaseClass {',
+ // ' static propTypes = {',
+ // ' b: PropTypes.string,',
+ // ' ...a.propTypes,',
+ // ' c: PropTypes.string,',
+ // ' d: PropTypes.string',
+ // ' }',
+ // '}'
+ // ].join('\n')
}, {
code: [
'export default class ClassWithSpreadInPropTypes extends BaseClass {',
@@ -1079,19 +1113,19 @@ ruleTester.run('sort-prop-types', rule, {
line: 6,
column: 5,
type: 'Property'
- }],
- output: [
- 'export default class ClassWithSpreadInPropTypes extends BaseClass {',
- ' static propTypes = {',
- ' b: PropTypes.string,',
- ' ...a.propTypes,',
- ' d: PropTypes.string,',
- ' f: PropTypes.string,',
- ' ...e.propTypes,',
- ' c: PropTypes.string',
- ' }',
- '}'
- ].join('\n')
+ }]
+ // output: [
+ // 'export default class ClassWithSpreadInPropTypes extends BaseClass {',
+ // ' static propTypes = {',
+ // ' b: PropTypes.string,',
+ // ' ...a.propTypes,',
+ // ' d: PropTypes.string,',
+ // ' f: PropTypes.string,',
+ // ' ...e.propTypes,',
+ // ' c: PropTypes.string',
+ // ' }',
+ // '}'
+ // ].join('\n')
}, {
code: [
'const propTypes = {',
@@ -1108,17 +1142,17 @@ ruleTester.run('sort-prop-types', rule, {
line: 3,
column: 3,
type: 'Property'
- }],
- output: [
- 'const propTypes = {',
- ' a: PropTypes.string,',
- ' b: PropTypes.string,',
- '};',
- 'const TextFieldLabel = (props) => {',
- ' return ;',
- '};',
- 'TextFieldLabel.propTypes = propTypes;'
- ].join('\n')
+ }]
+ // output: [
+ // 'const propTypes = {',
+ // ' a: PropTypes.string,',
+ // ' b: PropTypes.string,',
+ // '};',
+ // 'const TextFieldLabel = (props) => {',
+ // ' return ;',
+ // '};',
+ // 'TextFieldLabel.propTypes = propTypes;'
+ // ].join('\n')
}, {
code: `
class Component extends React.Component {
@@ -1149,23 +1183,23 @@ ruleTester.run('sort-prop-types', rule, {
line: 13,
column: 11,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- x: PropTypes.any,
- y: PropTypes.any,
- z: PropTypes.shape({
- a: PropTypes.any,
- b: PropTypes.bool,
- c: PropTypes.any,
- }),
- };
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // x: PropTypes.any,
+ // y: PropTypes.any,
+ // z: PropTypes.shape({
+ // a: PropTypes.any,
+ // b: PropTypes.bool,
+ // c: PropTypes.any,
+ // }),
+ // };
+ // `
}, {
code: `
class Component extends React.Component {
@@ -1187,19 +1221,19 @@ ruleTester.run('sort-prop-types', rule, {
line: 10,
column: 9,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- x: PropTypes.any,
- y: PropTypes.any,
- z: PropTypes.shape(),
- };
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // x: PropTypes.any,
+ // y: PropTypes.any,
+ // z: PropTypes.shape(),
+ // };
+ // `
}, {
code: `
class Component extends React.Component {
@@ -1221,19 +1255,19 @@ ruleTester.run('sort-prop-types', rule, {
line: 10,
column: 9,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- x: PropTypes.any,
- y: PropTypes.any,
- z: PropTypes.shape(someType),
- };
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // x: PropTypes.any,
+ // y: PropTypes.any,
+ // z: PropTypes.shape(someType),
+ // };
+ // `
}, {
code: `
class Component extends React.Component {
@@ -1280,24 +1314,24 @@ ruleTester.run('sort-prop-types', rule, {
line: 14,
column: 11,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- a: PropTypes.shape({
- C: PropTypes.string,
- a: PropTypes.any,
- b: PropTypes.bool,
- c: PropTypes.any,
- }),
- y: PropTypes.any,
- z: PropTypes.any,
- };
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // a: PropTypes.shape({
+ // C: PropTypes.string,
+ // a: PropTypes.any,
+ // b: PropTypes.bool,
+ // c: PropTypes.any,
+ // }),
+ // y: PropTypes.any,
+ // z: PropTypes.any,
+ // };
+ // `
}, {
code: `
class Component extends React.Component {
@@ -1330,24 +1364,24 @@ ruleTester.run('sort-prop-types', rule, {
line: 14,
column: 11,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- x: PropTypes.any,
- y: PropTypes.any,
- z: PropTypes.shape({
- a: PropTypes.any,
- b: PropTypes.bool,
- c: PropTypes.any,
- C: PropTypes.string,
- }),
- };
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // x: PropTypes.any,
+ // y: PropTypes.any,
+ // z: PropTypes.shape({
+ // a: PropTypes.any,
+ // b: PropTypes.bool,
+ // c: PropTypes.any,
+ // C: PropTypes.string,
+ // }),
+ // };
+ // `
}, {
code: `
class Component extends React.Component {
@@ -1375,24 +1409,24 @@ ruleTester.run('sort-prop-types', rule, {
line: 12,
column: 11,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- x: PropTypes.any,
- y: PropTypes.any,
- z: PropTypes.shape({
- c: PropTypes.number.isRequired,
- a: PropTypes.string,
- b: PropTypes.any,
- d: PropTypes.bool,
- }),
- };
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // x: PropTypes.any,
+ // y: PropTypes.any,
+ // z: PropTypes.shape({
+ // c: PropTypes.number.isRequired,
+ // a: PropTypes.string,
+ // b: PropTypes.any,
+ // d: PropTypes.bool,
+ // }),
+ // };
+ // `
}, {
code: `
class Component extends React.Component {
@@ -1426,25 +1460,25 @@ ruleTester.run('sort-prop-types', rule, {
line: 14,
column: 11,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- x: PropTypes.any,
- y: PropTypes.any,
- z: PropTypes.shape({
- a: PropTypes.string,
- b: PropTypes.any,
- c: PropTypes.number.isRequired,
- d: PropTypes.bool,
- onFoo: PropTypes.func,
- }),
- };
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // x: PropTypes.any,
+ // y: PropTypes.any,
+ // z: PropTypes.shape({
+ // a: PropTypes.string,
+ // b: PropTypes.any,
+ // c: PropTypes.number.isRequired,
+ // d: PropTypes.bool,
+ // onFoo: PropTypes.func,
+ // }),
+ // };
+ // `
}, {
code: `
class Component extends React.Component {
@@ -1478,26 +1512,26 @@ ruleTester.run('sort-prop-types', rule, {
line: 16,
column: 11,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- x: PropTypes.any,
- y: PropTypes.any,
- z: PropTypes.shape({
- a: PropTypes.string,
- b: PropTypes.any,
- c: PropTypes.number.isRequired,
- ...otherPropTypes,
- d: PropTypes.string,
- f: PropTypes.bool,
- }),
- };
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // x: PropTypes.any,
+ // y: PropTypes.any,
+ // z: PropTypes.shape({
+ // a: PropTypes.string,
+ // b: PropTypes.any,
+ // c: PropTypes.number.isRequired,
+ // ...otherPropTypes,
+ // d: PropTypes.string,
+ // f: PropTypes.bool,
+ // }),
+ // };
+ // `
}, {
code: `
class Component extends React.Component {
@@ -1539,23 +1573,23 @@ ruleTester.run('sort-prop-types', rule, {
line: 9,
column: 13,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- static propTypes = {
- a: PropTypes.shape({
- a: PropTypes.any,
- b: PropTypes.bool,
- c: PropTypes.any,
- }),
- y: PropTypes.any,
- z: PropTypes.any,
- };
- render() {
- return ;
- }
- }
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // static propTypes = {
+ // a: PropTypes.shape({
+ // a: PropTypes.any,
+ // b: PropTypes.bool,
+ // c: PropTypes.any,
+ // }),
+ // y: PropTypes.any,
+ // z: PropTypes.any,
+ // };
+ // render() {
+ // return ;
+ // }
+ // }
+ // `
}, {
code: [
'var First = createReactClass({',
@@ -1576,18 +1610,18 @@ ruleTester.run('sort-prop-types', rule, {
line: 4,
column: 5,
type: 'Property'
- }],
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' a: PropTypes.any,',
- ' z: PropTypes.string',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ }]
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' a: PropTypes.any,',
+ // ' z: PropTypes.string',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: [
'var First = createReactClass({',
@@ -1609,19 +1643,19 @@ ruleTester.run('sort-prop-types', rule, {
line: 4,
column: 5,
type: 'Property'
- }],
- output: [
- 'var First = createReactClass({',
- ' propTypes: {',
- ' a: PropTypes.any,',
- ' \'data-letter\': PropTypes.string,',
- ' e: PropTypes.any',
- ' },',
- ' render: function() {',
- ' return ;',
- ' }',
- '});'
- ].join('\n')
+ }]
+ // output: [
+ // 'var First = createReactClass({',
+ // ' propTypes: {',
+ // ' a: PropTypes.any,',
+ // ' \'data-letter\': PropTypes.string,',
+ // ' e: PropTypes.any',
+ // ' },',
+ // ' render: function() {',
+ // ' return ;',
+ // ' }',
+ // '});'
+ // ].join('\n')
}, {
code: `
class Component extends React.Component {
@@ -1642,18 +1676,18 @@ ruleTester.run('sort-prop-types', rule, {
line: 9,
column: 9,
type: 'Property'
- }],
- output: `
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- 0: PropTypes.any,
- 1: PropTypes.any,
- };
- `
+ }]
+ // output: `
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // 0: PropTypes.any,
+ // 1: PropTypes.any,
+ // };
+ // `
}, {
code: `
const shape = {
@@ -1685,23 +1719,23 @@ ruleTester.run('sort-prop-types', rule, {
line: 5,
column: 9,
type: 'Property'
- }],
- output: `
- const shape = {
- a: PropTypes.any,
- b: PropTypes.bool,
- c: PropTypes.any,
- };
- class Component extends React.Component {
- static propTypes = {
- x: PropTypes.shape(shape),
- };
+ }]
+ // output: `
+ // const shape = {
+ // a: PropTypes.any,
+ // b: PropTypes.bool,
+ // c: PropTypes.any,
+ // };
+ // class Component extends React.Component {
+ // static propTypes = {
+ // x: PropTypes.shape(shape),
+ // };
- render() {
- return ;
- }
- }
- `
+ // render() {
+ // return ;
+ // }
+ // }
+ // `
}, {
code: `
const shape = {
@@ -1731,21 +1765,21 @@ ruleTester.run('sort-prop-types', rule, {
line: 5,
column: 9,
type: 'Property'
- }],
- output: `
- const shape = {
- a: PropTypes.any,
- b: PropTypes.bool,
- c: PropTypes.any,
- };
- class Component extends React.Component {
- render() {
- return ;
- }
- }
- Component.propTypes = {
- x: PropTypes.shape(shape)
- };
- `
+ }]
+ // output: `
+ // const shape = {
+ // a: PropTypes.any,
+ // b: PropTypes.bool,
+ // c: PropTypes.any,
+ // };
+ // class Component extends React.Component {
+ // render() {
+ // return ;
+ // }
+ // }
+ // Component.propTypes = {
+ // x: PropTypes.shape(shape)
+ // };
+ // `
}]
});
diff --git a/tests/lib/rules/style-prop-object.js b/tests/lib/rules/style-prop-object.js
index 7f0817b5e1..251d5f79d9 100644
--- a/tests/lib/rules/style-prop-object.js
+++ b/tests/lib/rules/style-prop-object.js
@@ -192,6 +192,22 @@ ruleTester.run('style-prop-object', rule, {
' });',
'};'
].join('\n')
+ },
+ {
+ code: '',
+ options: [
+ {
+ allow: ['MyComponent']
+ }
+ ]
+ },
+ {
+ code: 'React.createElement(MyComponent, { style: "mySpecialStyle" })',
+ options: [
+ {
+ allow: ['MyComponent']
+ }
+ ]
}
],
invalid: [
@@ -263,6 +279,34 @@ ruleTester.run('style-prop-object', rule, {
column: 22,
type: 'Identifier'
}]
+ },
+ {
+ code: '',
+ options: [
+ {
+ allow: ['MyOtherComponent']
+ }
+ ],
+ errors: [{
+ message: 'Style prop value must be an object',
+ line: 1,
+ column: 14,
+ type: 'JSXAttribute'
+ }]
+ },
+ {
+ code: 'React.createElement(MyComponent, { style: "mySpecialStyle" })',
+ options: [
+ {
+ allow: ['MyOtherComponent']
+ }
+ ],
+ errors: [{
+ message: 'Style prop value must be an object',
+ line: 1,
+ column: 43,
+ type: 'Literal'
+ }]
}
]
});