Skip to content

Commit

Permalink
Additional tests for prop-types and no-unused-prop-types
Browse files Browse the repository at this point in the history
  • Loading branch information
alexzherdev committed Aug 15, 2018
1 parent fb745ab commit fb5c87f
Show file tree
Hide file tree
Showing 5 changed files with 332 additions and 38 deletions.
8 changes: 4 additions & 4 deletions lib/rules/no-unused-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ module.exports = {
function mustBeValidated(component) {
return Boolean(
component &&
!component.ignorePropsValidation
!component.ignoreUnusedPropTypesValidation
);
}

Expand Down Expand Up @@ -397,7 +397,7 @@ module.exports = {

const component = components.get(utils.getParentComponent());
const usedPropTypes = component && component.usedPropTypes || [];
let ignorePropsValidation = component && component.ignorePropsValidation || false;
let ignoreUnusedPropTypesValidation = component && component.ignoreUnusedPropTypesValidation || false;

switch (type) {
case 'direct':
Expand All @@ -414,7 +414,7 @@ module.exports = {
case 'destructuring':
for (let k = 0, l = (properties || []).length; k < l; k++) {
if (hasSpreadOperator(properties[k]) || properties[k].computed) {
ignorePropsValidation = true;
ignoreUnusedPropTypesValidation = true;
break;
}
const propName = getKeyValue(properties[k]);
Expand All @@ -441,7 +441,7 @@ module.exports = {

components.set(component ? component.node : node, {
usedPropTypes: usedPropTypes,
ignorePropsValidation: ignorePropsValidation
ignoreUnusedPropTypesValidation: ignoreUnusedPropTypesValidation
});
}

Expand Down
2 changes: 1 addition & 1 deletion lib/rules/prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ module.exports = {
return true;
}
// Consider every children as declared
if (propType.children === true) {
if (propType.children === true || propType.containsSpread) {
return true;
}
if (propType.acceptedProperties) {
Expand Down
10 changes: 5 additions & 5 deletions lib/util/propTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ module.exports = function propTypesInstructions(context, components, utils) {
}
});

// nested object type spread means we need to ignore/accept everything in this object
if (containsObjectTypeSpread) {
return {};
}
// Mark if this shape has spread. We will know to consider all props from this shape as having propTypes,
// but still have the ability to detect unused children of this shape.
shapeTypeDefinition.containsSpread = containsObjectTypeSpread;

return shapeTypeDefinition;
},

Expand Down Expand Up @@ -669,7 +669,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
JSXSpreadAttribute: function(node) {
const component = components.get(utils.getParentComponent());
components.set(component ? component.node : node, {
ignorePropsValidation: true
ignoreUnusedPropTypesValidation: true
});
},

Expand Down
258 changes: 230 additions & 28 deletions tests/lib/rules/no-unused-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -1801,34 +1801,6 @@ ruleTester.run('no-unused-prop-types', rule, {
' bar: PropTypes.bool',
'};'
].join('\n')
}, {
code: [
'type Person = {',
' ...data,',
' lastname: string',
'};',
'class Hello extends React.Component {',
' props: Person;',
' render () {',
' return <div>Hello {this.props.firstname}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint'
}, {
code: [
'type Person = {|',
' ...data,',
' lastname: string',
'|};',
'class Hello extends React.Component {',
' props: Person;',
' render () {',
' return <div>Hello {this.props.firstname}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint'
}, {
// The next two test cases are related to: https://github.com/yannickcr/eslint-plugin-react/issues/1183
code: [
Expand Down Expand Up @@ -2470,6 +2442,20 @@ ruleTester.run('no-unused-prop-types', rule, {
'}'
].join('\n'),
parser: 'babel-eslint'
}, {
code: [
'const foo = {};',
'class Hello extends React.Component {',
' render() {',
' const {firstname, lastname} = this.props.name;',
' return <div>{firstname} {lastname}</div>;',
' }',
'}',
'Hello.propTypes = {',
' name: PropTypes.shape(foo)',
'};'
].join('\n'),
parser: 'babel-eslint'
}, {
// issue #933
code: [
Expand Down Expand Up @@ -2913,6 +2899,23 @@ ruleTester.run('no-unused-prop-types', rule, {
}
`,
parser: 'babel-eslint'
}, {
code: [
'import type {BasePerson} from \'./types\'',
'type Props = {',
' person: {',
' ...$Exact<BasePerson>,',
' lastname: string',
' }',
'};',
'class Hello extends React.Component {',
' props: Props;',
' render () {',
' return <div>Hello {this.props.person.firstname}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
}
],

Expand Down Expand Up @@ -4475,6 +4478,48 @@ ruleTester.run('no-unused-prop-types', rule, {
errors: [{
message: '\'lastname\' PropType is defined but prop is never used'
}]
}, {
code: `
type Person = string;
class Hello extends React.Component<{ person: Person }> {
render () {
return <div />;
}
}
`,
settings: {react: {flowVersion: '0.53'}},
errors: [{
message: '\'person\' PropType is defined but prop is never used'
}],
parser: 'babel-eslint'
}, {
code: `
type Person = string;
class Hello extends React.Component<void, { person: Person }, void> {
render () {
return <div />;
}
}
`,
settings: {react: {flowVersion: '0.52'}},
errors: [{
message: '\'person\' PropType is defined but prop is never used'
}],
parser: 'babel-eslint'
}, {
code: `
function higherOrderComponent<P: { foo: string }>() {
return class extends React.Component<P> {
render() {
return <div />;
}
}
}
`,
errors: [{
message: '\'foo\' PropType is defined but prop is never used'
}],
parser: 'babel-eslint'
}, {
// issue #1506
code: [
Expand Down Expand Up @@ -4665,6 +4710,163 @@ ruleTester.run('no-unused-prop-types', rule, {
}, {
message: '\'a.b.c\' PropType is defined but prop is never used'
}]
}, {
code: `
type Props = { foo: string }
function higherOrderComponent<Props>() {
return class extends React.Component<Props> {
render() {
return <div />;
}
}
}
`,
parser: 'babel-eslint',
errors: [{
message: '\'foo\' PropType is defined but prop is never used'
}]
}, {
code: [
'type Person = {',
' ...data,',
' lastname: string',
'};',
'class Hello extends React.Component {',
' props: Person;',
' render () {',
' return <div>Hello {this.props.firstname}</div>;',
' }',
'}'
].join('\n'),
parser: '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 <div>Hello {this.props.firstname}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
errors: [{
message: '\'lastname\' PropType is defined but prop is never used'
}]
}, {
code: [
'type Person = {',
' ...$Exact<data>,',
' lastname: string',
'};',
'class Hello extends React.Component {',
' props: Person;',
' render () {',
' return <div>Hello {this.props.firstname}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
errors: [{
message: '\'lastname\' PropType is defined but prop is never used'
}]
}, {
code: [
'import type {Data} from \'./Data\'',
'type Person = {',
' ...Data,',
' lastname: string',
'};',
'class Hello extends React.Component {',
' props: Person;',
' render () {',
' return <div>Hello {this.props.bar}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
errors: [{
message: '\'lastname\' PropType is defined but prop is never used'
}]
}, {
code: [
'import type {Data} from \'some-libdef-like-flow-typed-provides\'',
'type Person = {',
' ...Data,',
' lastname: string',
'};',
'class Hello extends React.Component {',
' props: Person;',
' render () {',
' return <div>Hello {this.props.bar}</div>;',
' }',
'}'
].join('\n'),
parser: '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 <div>Hello {this.props.firstname}</div>;',
' }',
'}'
].join('\n'),
parser: '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 <div>Hello {this.props.firstname}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
errors: [{
message: '\'lastname\' PropType is defined but prop is never used'
}]
}, {
code: [
'import type {BasePerson} from \'./types\'',
'type Props = {',
' person: {',
' ...$Exact<BasePerson>,',
' lastname: string',
' }',
'};',
'class Hello extends React.Component {',
' props: Props;',
' render () {',
' return <div>Hello {this.props.person.firstname}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint',
options: [{skipShapeProps: false}],
errors: [{
message: '\'person.lastname\' PropType is defined but prop is never used'
}]
}

/* , {
Expand Down

0 comments on commit fb5c87f

Please sign in to comment.