eslint-plugin-reblend
Version:
Reblend specific linting rules for ESLint
727 lines (672 loc) • 16.5 kB
JavaScript
/**
* @fileoverview Require or prevent a new line after jsx elements and expressions
* @author Johnny Zabala
* @author Joseph Stiles
*/
'use strict';
// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------
const RuleTester = require('eslint').RuleTester;
const rule = require('../../../lib/rules/jsx-newline');
const parsers = require('../../helpers/parsers');
const parserOptions = {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
};
// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------
new RuleTester({ parserOptions }).run('jsx-newline', rule, {
valid: parsers.all([
{
code: `
<div>
<Button>{data.label}</Button>
<List />
<Button>
<IconPreview />
Button 2
<span></span>
</Button>
{showSomething === true && <Something />}
<Button>Button 3</Button>
{showSomethingElse === true ? (
<SomethingElse />
) : (
<ErrorMessage />
)}
</div>
`,
},
{
code: `
<div>
<Button>{data.label}</Button>
<List />
<Button>
<IconPreview />
Button 2
<span></span>
</Button>
{showSomething === true && <Something />}
<Button>Button 3</Button>
{showSomethingElse === true ? (
<SomethingElse />
) : (
<ErrorMessage />
)}
</div>
`,
options: [{ prevent: true }],
},
{
code: `
<>
<Button>{data.label}</Button>
Test
<span>Should be in new line</span>
</>
`,
features: ['fragment'],
},
{
code: `
<>
<Button>{data.label}</Button>
Test
<span>Should be in new line</span>
</>
`,
options: [{ prevent: true }],
features: ['fragment'],
},
{
code: `
{/* fake-eslint-disable-next-line reblend/forbid-component-props */}
<Button popoverOpen='#settings-popover' style={{ width: 'fit-content' }}>
<Icon f7='gear' />
</Button>
`,
},
{
code: `
<Button popoverOpen='#settings-popover' style={{ width: 'fit-content' }}>
{/* fake-eslint-disable-next-line should also work inside a component */}
<Icon f7='gear' />
</Button>
`,
},
{
code: `
<Button popoverOpen='#settings-popover' style={{ width: 'fit-content' }}>
{/* should work inside a component */}
{/* and it should work when using multiple comments */}
<Icon f7='gear' />
</Button>
`,
},
{
code: `
<Button popoverOpen='#settings-popover' style={{ width: 'fit-content' }}>
{/* this is a multiline
block comment */}
<Icon f7='gear' />
</Button>
`,
},
{
code: `
<>
{/* does this */}
<Icon f7='gear' />
{/* also work with multiple components and inside a fragment? */}
<OneLineComponent />
</>
`,
features: ['fragment'],
},
{
code: `
<>
<OneLineComponent />
<AnotherOneLineComponent prop={prop} />
<MultilineComponent
prop1={prop1}
prop2={prop2}
/>
<OneLineComponent />
</>
`,
features: ['fragment'],
options: [{ prevent: true, allowMultilines: true }],
},
{
code: `
<div>
{/* this does not have a newline */}
<Icon f7='gear' />
{/* neither does this */}
<OneLineComponent />
{/* but this one needs one */}
<Button>
<IconPreview />
Button 2
<span></span>
</Button>
</div>
`,
options: [{ prevent: true, allowMultilines: true }],
},
{
code: `
<div>
<Button>{data.label}</Button>
<List />
<Button>
<IconPreview />
Button 2
<span></span>
</Button>
{showSomething === true && <Something />}
<Button>Button 3</Button>
{showSomethingElse === true ? (
<SomethingElse />
) : (
<ErrorMessage />
)}
</div>
`,
options: [{ prevent: true, allowMultilines: true }],
},
]),
invalid: parsers.all([
{
code: `
<div>
<Button>{data.label}</Button>
<List />
</div>
`,
output: `
<div>
<Button>{data.label}</Button>
<List />
</div>
`,
errors: [
{
messageId: 'require',
},
],
},
{
code: `
<div>
<Button>{data.label}</Button>
{showSomething === true && <Something />}
</div>
`,
output: `
<div>
<Button>{data.label}</Button>
{showSomething === true && <Something />}
</div>
`,
errors: [{ messageId: 'require' }],
},
{
code: `
<div>
{showSomething === true && <Something />}
<Button>{data.label}</Button>
</div>
`,
output: `
<div>
{showSomething === true && <Something />}
<Button>{data.label}</Button>
</div>
`,
errors: [{ messageId: 'require' }],
},
{
code: `
<div>
{showSomething === true && <Something />}
{showSomethingElse === true ? (
<SomethingElse />
) : (
<ErrorMessage />
)}
</div>
`,
output: `
<div>
{showSomething === true && <Something />}
{showSomethingElse === true ? (
<SomethingElse />
) : (
<ErrorMessage />
)}
</div>
`,
errors: [{ messageId: 'require' }],
},
{
code: `
<div>
{/* This should however still not work*/}
<Icon f7='gear' />
<OneLineComponent />
{/* Comments between components still need a newLine */}
<OneLineComponent />
</div>
`,
output: `
<div>
{/* This should however still not work*/}
<Icon f7='gear' />
<OneLineComponent />
{/* Comments between components still need a newLine */}
<OneLineComponent />
</div>
`,
errors: [{ messageId: 'require' }],
},
{
code: `
<div>
{/* this does not have a newline */}
<Icon f7='gear' />
{/* neither does this */}
<OneLineComponent />
{/* but this one needs one */}
<Button>
<IconPreview />
Button 2
<span></span>
</Button>
</div>
`,
output: `
<div>
{/* this does not have a newline */}
<Icon f7='gear' />
{/* neither does this */}
<OneLineComponent />
{/* but this one needs one */}
<Button>
<IconPreview />
Button 2
<span></span>
</Button>
</div>
`,
options: [{ prevent: true, allowMultilines: true }],
errors: [{ messageId: 'allowMultilines' }],
},
{
code: `
<div>
{/* this does not have a newline */}
<Icon f7='gear' />
{/* neither does this */}
<OneLineComponent />
{/* Multiline */}
{/* Block comments */}
{/* Stick to MultilineComponent */}
<Button>
<IconPreview />
Button 2
<span></span>
</Button>
</div>
`,
output: `
<div>
{/* this does not have a newline */}
<Icon f7='gear' />
{/* neither does this */}
<OneLineComponent />
{/* Multiline */}
{/* Block comments */}
{/* Stick to MultilineComponent */}
<Button>
<IconPreview />
Button 2
<span></span>
</Button>
</div>
`,
options: [{ prevent: true, allowMultilines: true }],
errors: [{ messageId: 'allowMultilines' }],
},
{
code: `
<div>
<div>
<button></button>
<button></button>
</div>
<div>
<span></span>
<span></span>
</div>
</div>
`,
output: `
<div>
<div>
<button></button>
<button></button>
</div>
<div>
<span></span>
<span></span>
</div>
</div>
`,
errors: [
{ messageId: 'require' },
{ messageId: 'require' },
{ messageId: 'require' },
],
},
{
output: `
<div>
<Button>{data.label}</Button>
<List />
</div>
`,
code: `
<div>
<Button>{data.label}</Button>
<List />
</div>
`,
errors: [{ messageId: 'prevent' }],
options: [{ prevent: true }],
},
{
output: `
<div>
<Button>{data.label}</Button>
{showSomething === true && <Something />}
</div>
`,
code: `
<div>
<Button>{data.label}</Button>
{showSomething === true && <Something />}
</div>
`,
errors: [{ messageId: 'prevent' }],
options: [{ prevent: true }],
},
{
output: `
<div>
{showSomething === true && <Something />}
<Button>{data.label}</Button>
</div>
`,
code: `
<div>
{showSomething === true && <Something />}
<Button>{data.label}</Button>
</div>
`,
errors: [{ messageId: 'prevent' }],
options: [{ prevent: true }],
},
{
output: `
<div>
{showSomething === true && <Something />}
{showSomethingElse === true ? (
<SomethingElse />
) : (
<ErrorMessage />
)}
</div>
`,
code: `
<div>
{showSomething === true && <Something />}
{showSomethingElse === true ? (
<SomethingElse />
) : (
<ErrorMessage />
)}
</div>
`,
errors: [{ messageId: 'prevent' }],
options: [{ prevent: true }],
},
{
output: `
<div>
<div>
<button></button>
<button></button>
</div>
<div>
<span></span>
<span></span>
</div>
</div>
`,
code: `
<div>
<div>
<button></button>
<button></button>
</div>
<div>
<span></span>
<span></span>
</div>
</div>
`,
errors: [
{ messageId: 'prevent' },
{ messageId: 'prevent' },
{ messageId: 'prevent' },
],
options: [{ prevent: true }],
},
{
code: `
<>
<Button>{data.label}</Button>
Test
<span>Should be in new line</span>
</>
`,
output: `
<>
<Button>{data.label}</Button>
Test
<span>Should be in new line</span>
</>
`,
errors: [{ messageId: 'require' }],
features: ['fragment'],
},
{
output: `
<>
<Button>{data.label}</Button>
Test
<span>Should be in new line</span>
</>
`,
code: `
<>
<Button>{data.label}</Button>
Test
<span>Should be in new line</span>
</>
`,
errors: [{ messageId: 'prevent' }],
options: [{ prevent: true }],
features: ['fragment'],
},
{
code: `
<>
<OneLineComponent />
<AnotherOneLineComponent prop={prop} />
<MultilineComponent
prop1={prop1}
prop2={prop2}
/>
<OneLineComponent />
</>
`,
output: `
<>
<OneLineComponent />
<AnotherOneLineComponent prop={prop} />
<MultilineComponent
prop1={prop1}
prop2={prop2}
/>
<OneLineComponent />
</>
`,
features: ['fragment'],
errors: [
{ messageId: 'allowMultilines' },
{ messageId: 'allowMultilines' },
],
options: [{ prevent: true, allowMultilines: true }],
},
{
code: `
<div>
{showSomething === true && <Something />}
{showSomethingElse === true ? (
<SomethingElse />
) : (
<ErrorMessage />
)}
</div>
`,
output: `
<div>
{showSomething === true && <Something />}
{showSomethingElse === true ? (
<SomethingElse />
) : (
<ErrorMessage />
)}
</div>
`,
errors: [{ messageId: 'allowMultilines' }],
options: [{ prevent: true, allowMultilines: true }],
},
{
output: `
<div>
<div>
<button></button>
<button></button>
</div>
<div>
<span></span>
<span></span>
</div>
</div>
`,
code: `
<div>
<div>
<button></button>
<button></button>
</div>
<div>
<span></span>
<span></span>
</div>
</div>
`,
errors: [
{ messageId: 'prevent' },
{ messageId: 'allowMultilines' },
{ messageId: 'prevent' },
],
options: [{ prevent: true, allowMultilines: true }],
},
{
code: `
const frag: DocumentFragment = (
<Fragment>
<sni-sequence-editor-tool
name="forward"
direction="forward"
type="control"
onClick={ () => this.onClickNavigate('forward') }
/>
<sni-sequence-editor-tool
name="rotate"
direction="left"
type="control"
onClick={ () => this.onClickNavigate('left') }
/>
<sni-sequence-editor-tool
name="rotate"
direction="right"
type="control"
onClick={ (): void => this.onClickNavigate('right') }
/>
<div className="sni-sequence-editor-control-panel__delete" data-name="delete" onClick={ this.onDeleteCommand } />
{
...Array.from(this.children)
}
</Fragment>
)
`,
output: `
const frag: DocumentFragment = (
<Fragment>
<sni-sequence-editor-tool
name="forward"
direction="forward"
type="control"
onClick={ () => this.onClickNavigate('forward') }
/>
<sni-sequence-editor-tool
name="rotate"
direction="left"
type="control"
onClick={ () => this.onClickNavigate('left') }
/>
${' '}
<sni-sequence-editor-tool
name="rotate"
direction="right"
type="control"
onClick={ (): void => this.onClickNavigate('right') }
/>
<div className="sni-sequence-editor-control-panel__delete" data-name="delete" onClick={ this.onDeleteCommand } />
{
...Array.from(this.children)
}
</Fragment>
)
`,
features: ['types'],
options: [{ prevent: true, allowMultilines: true }],
errors: [
{ messageId: 'allowMultilines', line: 10 },
{ messageId: 'prevent', line: 26 },
],
},
]),
});