Skip to content

Commit

Permalink
chore: add tc for class components
Browse files Browse the repository at this point in the history
  • Loading branch information
akulsr0 committed May 15, 2024
1 parent 61981c7 commit 34b6a94
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 15 deletions.
46 changes: 32 additions & 14 deletions lib/rules/no-render-return-undefined.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,7 @@ module.exports = {
},

create(context) {
const handleFunctionalComponents = (node) => {
const fnName = (node.id && node.id.name) || node.parent.id.name;
const isReactComponent = fnName[0] === fnName[0].toUpperCase();
const returnStatement = astUtil.findReturnStatement(node);

if (!isReactComponent) return;

const isReturningUndefined = (returnStatement) => {
const variables = variableUtil.variablesInScope(context);
const returnNode = returnStatement && returnStatement.argument;
const returnIdentifierName = returnNode && returnNode.name;
Expand Down Expand Up @@ -73,13 +67,35 @@ module.exports = {
const returnsArrayHavingUndefined = Array.isArray(returnIdentifierValue)
&& returnIdentifierValue.some((el) => el.type === 'Identifier' && el.name === 'undefined');

if (
!returnStatement
|| returnIdentifierName === 'undefined'
|| returnIdentifierValue === undefined
|| (returnIdentifierValue && returnIdentifierValue.name === 'undefined')
|| returnsArrayHavingUndefined
) {
return !returnStatement
|| returnIdentifierName === 'undefined'
|| returnIdentifierValue === undefined
|| (returnIdentifierValue && returnIdentifierValue.name === 'undefined')
|| returnsArrayHavingUndefined;
};

const handleFunctionalComponents = (node) => {
const fnName = (node.id && node.id.name) || node.parent.id.name;

// Considering functions starting with Uppercase letters are react components
const isReactComponent = fnName[0] === fnName[0].toUpperCase();
const returnStatement = astUtil.findReturnStatement(node);

if (!isReactComponent) return;

if (isReturningUndefined(returnStatement)) {
report(context, messages.returnsUndefined, 'returnsUndefined', {
node,
});
}
};

const handleClassComponents = (node) => {
const componentProperties = astUtil.getComponentProperties(node);
const renderFnNode = componentProperties.find((prop) => prop.key.name === 'render');
const returnStatement = astUtil.findReturnStatement(renderFnNode);

if (isReturningUndefined(returnStatement)) {
report(context, messages.returnsUndefined, 'returnsUndefined', {
node,
});
Expand All @@ -89,6 +105,8 @@ module.exports = {
return {
FunctionDeclaration: handleFunctionalComponents,
ArrowFunctionExpression: handleFunctionalComponents,
ClassDeclaration: handleClassComponents,
ClassExpression: handleClassComponents,
};
},
};
230 changes: 229 additions & 1 deletion tests/lib/rules/no-render-return-undefined.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const parserOptions = {

const ruleTester = new RuleTester({ parserOptions });
ruleTester.run('no-render-return-undefined', rule, {
// Valid Cases
valid: parsers.all([
{
code: `
Expand Down Expand Up @@ -125,7 +126,128 @@ ruleTester.run('no-render-return-undefined', rule, {
}
`,
},

// Class Components
{
code: `
class App {
render() {
return 1;
}
}
`,
},
{
code: `
const App = class {
render() {
return 1;
}
}
`,
},
{
code: `
class App extends React.Component {
render() {
return 1;
}
}
`,
},
{
code: `
class App {
render() {
return "Hello World";
}
}
`,
},
{
code: `
const App = class {
render() {
return "Hello World";
}
}
`,
},
{
code: `
class App extends React.Component {
render() {
return "Hello World";
}
}
`,
},
{
code: `
class App {
render() {
return <div />;
}
}
`,
},
{
code: `
const App = class {
render() {
return <div />;
}
}
`,
},
{
code: `
class App extends React.Component {
render() {
return <div />;
}
}
`,
},
{
code: `
class App {
render() {
return [1, "Hello", <div />];
}
}
`,
},
{
code: `
class App extends React.Component {
render() {
return [1, "Hello", <div />];
}
}
`,
},
{
code: `
class App {
render() {
return null;
}
}
`,
},
{
code: `
class App extends React.Component {
render() {
return null;
}
}
`,
},
]),

// Invalid Cases
invalid: parsers.all([
{
code: `
Expand Down Expand Up @@ -235,7 +357,6 @@ ruleTester.run('no-render-return-undefined', rule, {
{
code: `
function foo() {}
function App() {
return foo();
}
Expand Down Expand Up @@ -286,5 +407,112 @@ ruleTester.run('no-render-return-undefined', rule, {
`,
errors: [{ messageId: 'returnsUndefined' }],
},
// Class Components
{
code: `
class App {
render() {
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
class App extends React.Component {
render() {
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
const App = class {
render() {}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
class App {
render() {
return;
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
class App extends React.Component {
render() {
return;
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
class App {
render() {
return undefined;
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
class App extends React.Component {
render() {
return undefined;
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
class App {
render() {
return [undefined];
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
class App extends React.Component {
render() {
return [undefined];
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
class App {
render() {
return [1, undefined];
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
{
code: `
class App extends React.Component {
render() {
return [1, undefined];
}
}
`,
errors: [{ messageId: 'returnsUndefined' }],
},
]),
});

0 comments on commit 34b6a94

Please sign in to comment.