123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777 |
- /**
- * @fileoverview Enforces consistent naming for boolean props
- * @author Ev Haus
- */
- 'use strict';
- // ------------------------------------------------------------------------------
- // Requirements
- // ------------------------------------------------------------------------------
- const rule = require('../../../lib/rules/boolean-prop-naming');
- const RuleTester = require('eslint').RuleTester;
- require('babel-eslint');
- const parserOptions = {
- ecmaVersion: 2018,
- sourceType: 'module',
- ecmaFeatures: {
- jsx: true
- }
- };
- // ------------------------------------------------------------------------------
- // Tests
- // ------------------------------------------------------------------------------
- const ruleTester = new RuleTester({parserOptions});
- ruleTester.run('boolean-prop-naming', rule, {
- valid: [{
- // Should support both `is` and `has` prefixes by default
- code: `
- var Hello = createReactClass({
- propTypes: {isSomething: PropTypes.bool, hasValue: PropTypes.bool},
- render: function() { return <div />; }
- });
- `
- }, {
- // createReactClass components with PropTypes
- code: `
- var Hello = createReactClass({
- propTypes: {isSomething: PropTypes.bool},
- render: function() { return <div />; }
- });
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }]
- }, {
- // createReactClass components with React.PropTypes
- code: `
- var Hello = createReactClass({
- propTypes: {isSomething: React.PropTypes.bool},
- render: function() { return <div />; }
- });
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }]
- }, {
- // React.createClass components with PropTypes
- code: `
- var Hello = React.createClass({
- propTypes: {isSomething: PropTypes.bool},
- render: function() { return <div />; }
- });
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- settings: {
- react: {
- createClass: 'createClass'
- }
- }
- }, {
- // React.createClass components with non-boolean PropTypes
- code: `
- var Hello = React.createClass({
- propTypes: {something: PropTypes.any},
- render: function() { return <div />; }
- });
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- settings: {
- react: {
- createClass: 'createClass'
- }
- }
- }, {
- // ES6 components as React.Component with boolean PropTypes
- code: `
- class Hello extends React.Component {
- render () { return <div />; }
- }
- Hello.propTypes = {isSomething: PropTypes.bool}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }]
- }, {
- // ES6 components as React.Component with non-boolean PropTypes
- code: `
- class Hello extends React.Component {
- render () { return <div />; }
- }
- Hello.propTypes = wrap({ a: PropTypes.bool })
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }]
- }, {
- code: `
- class Hello extends React.Component {
- render () { return <div />; }
- }
- Hello.propTypes = {something: PropTypes.any}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }]
- }, {
- // ES6 components as Component with boolean PropTypes
- code: `
- class Hello extends Component {
- render () { return <div />; }
- }
- Hello.propTypes = {isSomething: PropTypes.bool}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }]
- }, {
- // ES6 components with static class properties and PropTypes
- code: `
- class Hello extends React.Component {
- static propTypes = {isSomething: PropTypes.bool};
- render () { return <div />; }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // ES6 components with static class properties and Object.spread syntax in PropTypes
- code: `
- const spreadProps = { aSpreadProp: PropTypes.string };
- class Hello extends React.Component {
- static propTypes = {isSomething: PropTypes.bool, ...spreadProps};
- render () { return <div />; }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // ES6 components as Component with boolean PropTypes and Object.spread syntax in PropTypes
- code: `
- const spreadProps = { aSpreadProp: PropTypes.string };
- class Hello extends Component {
- render () { return <div />; }
- }
- Hello.propTypes = {isSomething: PropTypes.bool, ...spreadProps}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }]
- }, {
- // ES6 components with static class properties and React.PropTypes
- code: `
- class Hello extends React.Component {
- static propTypes = {isSomething: React.PropTypes.bool};
- render () { return <div />; }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // ES6 components with static class properties an non-booleans
- code: `
- class Hello extends React.Component {
- static propTypes = {something: PropTypes.any};
- render () { return <div />; }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // ES6 components and Flowtype booleans
- code: `
- class Hello extends React.Component {
- props: {isSomething: boolean};
- render () { return <div />; }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // ES6 components and Flowtype non-booleans
- code: `
- class Hello extends React.Component {
- props: {something: any};
- render () { return <div />; }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // Stateless components
- code: `
- var Hello = ({isSomething}) => { return <div /> }
- Hello.propTypes = {isSomething: PropTypes.bool};
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // Functional components and Flowtype booleans
- code: `
- type Props = {
- isSomething: boolean;
- };
- function Hello(props: Props): React.Element { return <div /> }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // Custom `propTypeNames` option
- code: `
- class Hello extends React.Component {
- static propTypes = {
- isSomething: PropTypes.mutuallyExclusiveTrueProps,
- something: PropTypes.bool
- };
- render () { return <div />; }
- }
- `,
- options: [{
- propTypeNames: ['mutuallyExclusiveTrueProps'],
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // Custom PropTypes that are specified as variables
- code: `
- class Hello extends React.Component {
- static propTypes = {
- isSomething: mutuallyExclusiveTrueProps,
- isSomethingElse: bool
- };
- render () { return <div />; }
- }
- `,
- options: [{
- propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'],
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // Ensure rule doesn't crash on destructured objects [Issue #1369]
- code: `
- var x = {a: 1}
- var y = {...x}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // Ensure rule doesn't crash on on components reference old-style Flow props
- code: `
- class Hello extends PureComponent {
- props: PropsType;
- render () { return <div /> }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint'
- }, {
- // No propWrapperFunctions setting
- code: `
- function Card(props) {
- return <div>{props.showScore ? 'yeh' : 'no'}</div>;
- }
- Card.propTypes = merge({}, Card.propTypes, {
- showScore: PropTypes.bool
- });`,
- options: [{
- rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
- }]
- }, {
- // Ensure the rule does not throw when a prop isRequired when ES5.
- code: `
- var Hello = createReactClass({
- propTypes: {isSomething: PropTypes.bool.isRequired, hasValue: PropTypes.bool.isRequired},
- render: function() { return <div />; }
- });
- `
- }, {
- // Ensure the rule does not throw when a prop isRequired when ES6 with static properties.
- code: `
- class Hello extends React.Component {
- static propTypes = {
- isSomething: PropTypes.bool.isRequired,
- hasValue: PropTypes.bool.isRequired
- };
- render() {
- return (
- <div />
- );
- }
- }
- `,
- parser: 'babel-eslint'
- }, {
- // Ensure the rule does not throw when a prop isRequired when ES6 without static properties.
- code: `
- class Hello extends React.Component {
- render() {
- return (
- <div />
- );
- }
- }
- Hello.propTypes = {
- isSomething: PropTypes.bool.isRequired,
- hasValue: PropTypes.bool.isRequired
- }
- `
- }, {
- // Ensure the rule does not throw when a shape prop isRequired.
- code: `
- var Hello = createReactClass({
- propTypes: {something: PropTypes.shape({}).isRequired},
- render: function() { return <div />; }
- });
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }]
- }],
- invalid: [{
- // createReactClass components with PropTypes
- code: `
- var Hello = createReactClass({
- propTypes: {something: PropTypes.bool},
- render: function() { return <div />; }
- });
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // createReactClass components with React.PropTypes
- code: `
- var Hello = createReactClass({
- propTypes: {something: React.PropTypes.bool},
- render: function() { return <div />; }
- });
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // React.createClass components with PropTypes
- code: `
- var Hello = React.createClass({
- propTypes: {something: PropTypes.bool},
- render: function() { return <div />; }
- });
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- settings: {
- react: {
- createClass: 'createClass'
- }
- },
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // ES6 components as React.Component with boolean PropTypes
- code: `
- class Hello extends React.Component {
- render () { return <div />; }
- }
- Hello.propTypes = {something: PropTypes.bool}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // ES6 components as Component with non-boolean PropTypes
- code: `
- class Hello extends Component {
- render () { return <div />; }
- }
- Hello.propTypes = {something: PropTypes.bool}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // ES6 components as React.Component with non-boolean PropTypes
- code: `
- class Hello extends React.Component {
- static propTypes = {something: PropTypes.bool};
- render () { return <div />; }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint',
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // ES6 components as React.Component with non-boolean PropTypes and Object.spread syntax
- code: `
- const spreadProps = { aSpreadProp: PropTypes.string };
- class Hello extends Component {
- render () { return <div />; }
- }
- Hello.propTypes = {something: PropTypes.bool, ...spreadProps}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // ES6 components as React.Component with static class property, non-boolean PropTypes, and Object.spread syntax
- code: `
- const spreadProps = { aSpreadProp: PropTypes.string };
- class Hello extends React.Component {
- static propTypes = {something: PropTypes.bool, ...spreadProps};
- render () { return <div />; }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint',
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // ES6 components as React.Component with non-boolean PropTypes
- code: `
- class Hello extends React.Component {
- props: {something: boolean};
- render () { return <div />; }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint',
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- var Hello = ({something}) => { return <div /> }
- Hello.propTypes = {something: PropTypes.bool};
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint',
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- type Props = {
- something: boolean;
- };
- function Hello(props: Props): React.Element { return <div /> }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint',
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // ES6 components and Flowtype non-booleans
- code: `
- class Hello extends React.Component {
- static propTypes = {something: PropTypes.mutuallyExclusiveTrueProps};
- render () { return <div />; }
- }
- `,
- options: [{
- propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'],
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint',
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- class Hello extends React.Component {
- static propTypes = {
- something: PropTypes.mutuallyExclusiveTrueProps,
- somethingElse: PropTypes.bool
- };
- render () { return <div />; }
- }
- `,
- options: [{
- propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'],
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint',
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }, {
- message: 'Prop name (somethingElse) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- class Hello extends React.Component {
- static propTypes = {
- something: mutuallyExclusiveTrueProps,
- somethingElse: bool
- };
- render () { return <div />; }
- }
- `,
- options: [{
- propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'],
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint',
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }, {
- message: 'Prop name (somethingElse) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- function Card(props) {
- return <div>{props.showScore ? 'yeh' : 'no'}</div>;
- }
- Card.propTypes = merge({}, Card.propTypes, {
- showScore: PropTypes.bool
- });`,
- settings: {
- propWrapperFunctions: ['merge']
- },
- options: [{
- rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (showScore) doesn\'t match rule (^(is|has)[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- function Card(props) {
- return <div>{props.showScore ? 'yeh' : 'no'}</div>;
- }
- Card.propTypes = Object.assign({}, Card.propTypes, {
- showScore: PropTypes.bool
- });`,
- settings: {
- propWrapperFunctions: ['Object.assign']
- },
- options: [{
- rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (showScore) doesn\'t match rule (^(is|has)[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- function Card(props) {
- return <div>{props.showScore ? 'yeh' : 'no'}</div>;
- }
- Card.propTypes = _.assign({}, Card.propTypes, {
- showScore: PropTypes.bool
- });`,
- settings: {
- propWrapperFunctions: ['_.assign']
- },
- options: [{
- rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (showScore) doesn\'t match rule (^(is|has)[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- function Card(props) {
- return <div>{props.showScore ? 'yeh' : 'no'}</div>;
- }
- Card.propTypes = forbidExtraProps({
- showScore: PropTypes.bool
- });`,
- settings: {
- propWrapperFunctions: ['forbidExtraProps']
- },
- options: [{
- rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (showScore) doesn\'t match rule (^(is|has)[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- class Card extends React.Component {
- render() {
- return <div>{props.showScore ? 'yeh' : 'no'}</div>;
- }
- }
- Card.propTypes = forbidExtraProps({
- showScore: PropTypes.bool
- });`,
- settings: {
- propWrapperFunctions: ['forbidExtraProps']
- },
- options: [{
- rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (showScore) doesn\'t match rule (^(is|has)[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- code: `
- class Card extends React.Component {
- static propTypes = forbidExtraProps({
- showScore: PropTypes.bool
- });
- render() {
- return <div>{props.showScore ? 'yeh' : 'no'}</div>;
- }
- }`,
- parser: 'babel-eslint',
- settings: {
- propWrapperFunctions: ['forbidExtraProps']
- },
- options: [{
- rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (showScore) doesn\'t match rule (^(is|has)[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // If a custom message is provided, use it.
- code: `
- class Hello extends React.Component {
- render () { return <div />; }
- }
- Hello.propTypes = {something: PropTypes.bool}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+',
- message: 'Boolean prop names must begin with either \'is\' or \'has\''
- }],
- errors: [{
- message: 'Boolean prop names must begin with either \'is\' or \'has\''
- }]
- }, {
- // Custom messages use ESLint string templating.
- code: `
- class Hello extends React.Component {
- render () { return <div />; }
- }
- Hello.propTypes = {something: PropTypes.bool}
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+',
- message: 'It is better if your prop ({{ propName }}) matches this pattern: ({{ pattern }})'
- }],
- errors: [{
- message: 'It is better if your prop (something) matches this pattern: (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // Works when a prop isRequired in ES5.
- code: `
- var Hello = createReactClass({
- propTypes: {something: PropTypes.bool.isRequired},
- render: function() { return <div />; }
- });
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // Works when a prop isRequired in ES6 with static properties.
- code: `
- class Hello extends React.Component {
- static propTypes = {
- something: PropTypes.bool.isRequired
- };
- render() {
- return (
- <div />
- );
- }
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- parser: 'babel-eslint',
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }, {
- // Works when a prop isRequired in ES6 without static properties.
- code: `
- class Hello extends React.Component {
- render() {
- return (
- <div />
- );
- }
- }
- Hello.propTypes = {
- something: PropTypes.bool.isRequired
- }
- `,
- options: [{
- rule: '^is[A-Z]([A-Za-z0-9]?)+'
- }],
- errors: [{
- message: 'Prop name (something) doesn\'t match rule (^is[A-Z]([A-Za-z0-9]?)+)'
- }]
- }]
- });
|