123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- /**
- * @fileoverview Enforce curly braces or disallow unnecessary curly braces in JSX
- * @author Jacky Ho
- */
- 'use strict';
- /* eslint-disable quotes */ // For better readability on tests involving quotes
- // ------------------------------------------------------------------------------
- // Requirements
- // ------------------------------------------------------------------------------
- const rule = require('../../../lib/rules/jsx-curly-brace-presence');
- const RuleTester = require('eslint').RuleTester;
- const parserOptions = {
- sourceType: 'module',
- ecmaFeatures: {
- jsx: true
- }
- };
- const missingCurlyMessage = 'Need to wrap this literal in a JSX expression.';
- const unnecessaryCurlyMessage = 'Curly braces are unnecessary here.';
- // ------------------------------------------------------------------------------
- // Tests
- // ------------------------------------------------------------------------------
- const ruleTester = new RuleTester({parserOptions});
- ruleTester.run('jsx-curly-brace-presence', rule, {
- valid: [
- {
- code: '<App {...props}>foo</App>'
- },
- {
- code: '<App {...props}>foo</App>',
- options: [{props: 'never'}]
- },
- /*
- * There is no way to inject the space into JSX without an expression container
- * so this format should always be allowed regardless of the `children` option.
- */
- {
- code: '<App>{\' \'}</App>'
- },
- {
- code: '<App>{\' \'}</App>'
- },
- {
- code: '<App>{\' \'}</App>',
- options: [{children: 'never'}]
- },
- {
- code: '<App>{\' \'}</App>',
- options: [{children: 'never'}]
- },
- {
- code: '<App>{\' \'}</App>',
- options: [{children: 'always'}]
- },
- {
- code: '<App>{\' \'}</App>',
- options: [{children: 'always'}]
- },
- {
- code: '<App {...props}>foo</App>',
- options: [{props: 'always'}]
- },
- {
- code: '<App>{`Hello ${word} World`}</App>',
- options: [{children: 'never'}]
- },
- {
- code: '<App>{`Hello \\n World`}</App>',
- options: [{children: 'never'}]
- },
- {
- code: '<App>{`Hello ${word} World`}{`foo`}</App>',
- options: [{children: 'never'}]
- },
- {
- code: '<App prop={`foo ${word} bar`}>foo</App>',
- options: [{props: 'never'}]
- },
- {
- code: '<App prop={`foo ${word} bar`} />',
- options: [{props: 'never'}]
- },
- {
- code: '<App>{<myApp></myApp>}</App>'
- },
- {
- code: '<App>{[]}</App>'
- },
- {
- code: '<App>foo</App>'
- },
- {
- code: '<App>{"foo"}{<Component>bar</Component>}</App>'
- },
- {
- code: `<App prop='bar'>foo</App>`
- },
- {
- code: '<App prop={true}>foo</App>'
- },
- {
- code: '<App prop>foo</App>'
- },
- {
- code: `<App prop='bar'>{'foo \\n bar'}</App>`
- },
- {
- code: `<MyComponent prop='bar'>foo</MyComponent>`,
- options: [{props: 'never'}]
- },
- {
- code: `<MyComponent prop="bar">foo</MyComponent>`,
- options: [{props: 'never'}]
- },
- {
- code: '<MyComponent>foo</MyComponent>',
- options: [{children: 'never'}]
- },
- {
- code: '<MyComponent>{<App/>}{"123"}</MyComponent>',
- options: [{children: 'never'}]
- },
- {
- code: `<App>{"foo 'bar' \\"foo\\" bar"}</App>`,
- options: [{children: 'never'}]
- },
- {
- code: `<MyComponent prop={'bar'}>foo</MyComponent>`,
- options: [{props: 'always'}]
- },
- {
- code: `<MyComponent>{'foo'}</MyComponent>`,
- options: [{children: 'always'}]
- },
- {
- code: `<MyComponent prop={"bar"}>foo</MyComponent>`,
- options: [{props: 'always'}]
- },
- {
- code: `<MyComponent>{"foo"}</MyComponent>`,
- options: [{children: 'always'}]
- },
- {
- code: `<MyComponent>{'foo'}</MyComponent>`,
- options: [{children: 'ignore'}]
- },
- {
- code: `<MyComponent prop={'bar'}>foo</MyComponent>`,
- options: [{props: 'ignore'}]
- },
- {
- code: '<MyComponent>foo</MyComponent>',
- options: [{children: 'ignore'}]
- },
- {
- code: `<MyComponent prop='bar'>foo</MyComponent>`,
- options: [{props: 'ignore'}]
- },
- {
- code: `<MyComponent prop="bar">foo</MyComponent>`,
- options: [{props: 'ignore'}]
- },
- {
- code: `<MyComponent prop='bar'>{'foo'}</MyComponent>`,
- options: [{children: 'always', props: 'never'}]
- },
- {
- code: `<MyComponent prop={'bar'}>foo</MyComponent>`,
- options: [{children: 'never', props: 'always'}]
- },
- {
- code: `<MyComponent prop={'bar'}>{'foo'}</MyComponent>`,
- options: ['always']
- },
- {
- code: `<MyComponent prop={"bar"}>{"foo"}</MyComponent>`,
- options: ['always']
- },
- {
- code: `<MyComponent prop={"bar"} attr={'foo'} />`,
- options: ['always']
- },
- {
- code: `<MyComponent prop="bar" attr='foo' />`,
- options: ['never']
- },
- {
- code: `<MyComponent prop='bar'>foo</MyComponent>`,
- options: ['never']
- },
- {
- code: '<MyComponent prop={`bar ${word} foo`}>{`foo ${word}`}</MyComponent>',
- options: ['never']
- },
- {
- code: '<MyComponent>{"div { margin-top: 0; }"}</MyComponent>',
- options: ['never']
- },
- {
- code: '<MyComponent>{"<Foo />"}</MyComponent>',
- options: ['never']
- },
- {
- code: '<MyComponent prop={"{ style: true }"}>bar</MyComponent>',
- options: ['never']
- },
- {
- code: '<MyComponent prop={"< style: true >"}>foo</MyComponent>',
- options: ['never']
- },
- {
- code: '<MyComponent prop={"Hello \\u1026 world"}>bar</MyComponent>',
- options: ['never']
- },
- {
- code: '<MyComponent>{"Hello \\u1026 world"}</MyComponent>',
- options: ['never']
- },
- {
- code: '<MyComponent prop={"Hello · world"}>bar</MyComponent>',
- options: ['never']
- },
- {
- code: '<MyComponent>{"Hello · world"}</MyComponent>',
- options: ['never']
- },
- {
- code: '<MyComponent>{"Hello \\n world"}</MyComponent>',
- options: ['never']
- },
- {
- code: ['<a a={"start\\', '\\', 'end"}/>'].join('/n'),
- options: ['never']
- }
- ],
- invalid: [
- {
- code: '<App prop={`foo`} />',
- output: '<App prop="foo" />',
- options: [{props: 'never'}],
- errors: [{message: unnecessaryCurlyMessage}]
- },
- {
- code: '<App prop={`foo`}>foo</App>',
- output: '<App prop="foo">foo</App>',
- options: [{props: 'never'}],
- errors: [{message: unnecessaryCurlyMessage}]
- },
- {
- code: '<App>{`foo`}</App>',
- output: '<App>foo</App>',
- options: [{children: 'never'}],
- errors: [{message: unnecessaryCurlyMessage}]
- },
- {
- code: `<MyComponent>{'foo'}</MyComponent>`,
- output: '<MyComponent>foo</MyComponent>',
- errors: [{message: unnecessaryCurlyMessage}]
- },
- {
- code: `<MyComponent prop={'bar'}>foo</MyComponent>`,
- output: `<MyComponent prop="bar">foo</MyComponent>`,
- errors: [{message: unnecessaryCurlyMessage}]
- },
- {
- code: `<MyComponent>{'foo'}</MyComponent>`,
- output: '<MyComponent>foo</MyComponent>',
- options: [{children: 'never'}],
- errors: [{message: unnecessaryCurlyMessage}]
- },
- {
- code: `<MyComponent prop={'bar'}>foo</MyComponent>`,
- output: '<MyComponent prop="bar">foo</MyComponent>',
- options: [{props: 'never'}],
- errors: [{message: unnecessaryCurlyMessage}]
- },
- {
- code: `<MyComponent prop='bar'>foo</MyComponent>`,
- output: '<MyComponent prop={"bar"}>foo</MyComponent>',
- options: [{props: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: `<MyComponent prop="foo 'bar'">foo</MyComponent>`,
- output: `<MyComponent prop={"foo 'bar'"}>foo</MyComponent>`,
- options: [{props: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: `<MyComponent prop='foo "bar"'>foo</MyComponent>`,
- output: `<MyComponent prop={"foo \\"bar\\""}>foo</MyComponent>`,
- options: [{props: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: `<MyComponent prop="foo 'bar'">foo</MyComponent>`,
- output: `<MyComponent prop={"foo 'bar'"}>foo</MyComponent>`,
- options: [{props: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: '<MyComponent>foo bar </MyComponent>',
- output: `<MyComponent>{"foo bar "}</MyComponent>`,
- options: [{children: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: `<MyComponent prop="foo 'bar' \\n ">foo</MyComponent>`,
- output: `<MyComponent prop={"foo 'bar' \\\\n "}>foo</MyComponent>`,
- options: [{props: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: '<MyComponent>foo bar \\r </MyComponent>',
- output: '<MyComponent>{"foo bar \\\\r "}</MyComponent>',
- options: [{children: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: `<MyComponent>foo bar 'foo'</MyComponent>`,
- output: `<MyComponent>{"foo bar 'foo'"}</MyComponent>`,
- options: [{children: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: '<MyComponent>foo bar "foo"</MyComponent>',
- output: '<MyComponent>{"foo bar \\"foo\\""}</MyComponent>',
- options: [{children: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: '<MyComponent>foo bar <App/></MyComponent>',
- output: '<MyComponent>{"foo bar "}<App/></MyComponent>',
- options: [{children: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: '<MyComponent>foo \\n bar</MyComponent>',
- output: '<MyComponent>{"foo \\\\n bar"}</MyComponent>',
- options: [{children: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: '<MyComponent>foo \\u1234 bar</MyComponent>',
- output: '<MyComponent>{"foo \\\\u1234 bar"}</MyComponent>',
- options: [{children: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: `<MyComponent prop='foo \\u1234 bar' />`,
- output: '<MyComponent prop={"foo \\\\u1234 bar"} />',
- options: [{props: 'always'}],
- errors: [{message: missingCurlyMessage}]
- },
- {
- code: `<MyComponent prop={'bar'}>{'foo'}</MyComponent>`,
- output: '<MyComponent prop="bar">foo</MyComponent>',
- options: ['never'],
- errors: [
- {message: unnecessaryCurlyMessage}, {message: unnecessaryCurlyMessage}
- ]
- },
- {
- code: `<MyComponent prop='bar'>foo</MyComponent>`,
- output: '<MyComponent prop={"bar"}>{"foo"}</MyComponent>',
- options: ['always'],
- errors: [
- {message: missingCurlyMessage}, {message: missingCurlyMessage}
- ]
- },
- {
- code: `<App prop={'foo'} attr={" foo "} />`,
- output: '<App prop="foo" attr=" foo " />',
- errors: [
- {message: unnecessaryCurlyMessage}, {message: unnecessaryCurlyMessage}
- ],
- options: [{props: 'never'}]
- },
- {
- code: `<App prop='foo' attr="bar" />`,
- output: '<App prop={"foo"} attr={"bar"} />',
- errors: [
- {message: missingCurlyMessage}, {message: missingCurlyMessage}
- ],
- options: [{props: 'always'}]
- },
- {
- code: `<App prop='foo' attr={"bar"} />`,
- output: `<App prop={"foo"} attr={"bar"} />`,
- errors: [{message: missingCurlyMessage}],
- options: [{props: 'always'}]
- },
- {
- code: `<App prop={'foo'} attr='bar' />`,
- output: `<App prop={'foo'} attr={"bar"} />`,
- errors: [{message: missingCurlyMessage}],
- options: [{props: 'always'}]
- },
- {
- code: `<App prop='foo · bar' />`,
- errors: [{message: missingCurlyMessage}],
- options: [{props: 'always'}]
- },
- {
- code: '<App>foo · bar</App>',
- errors: [{message: missingCurlyMessage}],
- options: [{children: 'always'}]
- },
- {
- code: `<App>{'foo "bar"'}</App>`,
- output: `<App>foo "bar"</App>`,
- errors: [{message: unnecessaryCurlyMessage}],
- options: [{children: 'never'}]
- },
- {
- code: `<App>{"foo 'bar'"}</App>`,
- output: `<App>foo 'bar'</App>`,
- errors: [{message: unnecessaryCurlyMessage}],
- options: [{children: 'never'}]
- },
- {
- code: [
- '<App prop=" ',
- ' a ',
- ' b c',
- ' d',
- '">',
- ' a',
- ' b c ',
- ' d ',
- '</App>'
- ].join('\n'),
- errors: [
- {message: missingCurlyMessage}, {message: missingCurlyMessage}
- ],
- options: ['always']
- },
- {
- code: [
- `<App prop=' `,
- ' a ',
- ' b c',
- ' d',
- `'>`,
- ' a',
- ' b c ',
- ' d ',
- '</App>'
- ].join('\n'),
- errors: [
- {message: missingCurlyMessage}, {message: missingCurlyMessage}
- ],
- options: ['always']
- }
- ]
- });
|