diff --git a/lib/util/hasTextContentChild.ts b/lib/util/hasTextContentChild.ts index 5f68401..1afb4b0 100644 --- a/lib/util/hasTextContentChild.ts +++ b/lib/util/hasTextContentChild.ts @@ -4,7 +4,7 @@ import { TSESTree } from "@typescript-eslint/types"; /** - * hasTextContentChild - determines if a component has text content as a child e.g. + * hasTextContentChild - determines if a component has text content as a child, e.g., , , , or * @param {*} node JSXElement * @returns boolean */ @@ -14,12 +14,28 @@ const hasTextContentChild = (node?: TSESTree.JSXElement) => { return false; } - if (node.children == null || node.children == undefined || node.children.length === 0) { + if (!node.children || node.children.length === 0) { return false; } const result = node.children.filter(element => { - return element.type === "JSXText" && element.value.trim().length > 0; + // Check for JSXText with non-whitespace content + if (element.type === "JSXText" && element.value.trim().length > 0) { + return true; + } + + // Check for JSXExpressionContainer with valid expression content + if ( + element.type === "JSXExpressionContainer" && + element.expression && + ((element.expression.type === "Literal" && String(element.expression.value).trim().length > 0) || + element.expression.type === "CallExpression" || + element.expression.type === "Identifier") + ) { + return true; + } + + return false; }); return result.length !== 0; diff --git a/tests/lib/rules/utils/hasTextContentChild.test.ts b/tests/lib/rules/utils/hasTextContentChild.test.ts index 056963e..79019a3 100644 --- a/tests/lib/rules/utils/hasTextContentChild.test.ts +++ b/tests/lib/rules/utils/hasTextContentChild.test.ts @@ -22,7 +22,7 @@ describe("hasTextContentChild", () => { expect(hasTextContentChild(node)).toBe(false); }); - it("should return false when node.children has no JSXText elements with non-whitespace content", () => { + it("should return false when node.children has no JSXText or relevant JSXExpressionContainer content", () => { const node: TSESTree.JSXElement = { children: [{ type: "JSXElement" }, { type: "JSXExpressionContainer" }] } as any; @@ -42,4 +42,32 @@ describe("hasTextContentChild", () => { } as any; expect(hasTextContentChild(node)).toBe(false); }); + + it("should return true when node.children has JSXExpressionContainer with a literal string", () => { + const node: TSESTree.JSXElement = { + children: [{ type: "JSXExpressionContainer", expression: { type: "Literal", value: "Hello" } }] + } as any; + expect(hasTextContentChild(node)).toBe(true); + }); + + it("should return true when node.children has JSXExpressionContainer with a function call", () => { + const node: TSESTree.JSXElement = { + children: [{ type: "JSXExpressionContainer", expression: { type: "CallExpression", callee: { name: "myFunc" } } }] + } as any; + expect(hasTextContentChild(node)).toBe(true); + }); + + it("should return true when node.children has JSXExpressionContainer with an identifier (variable)", () => { + const node: TSESTree.JSXElement = { + children: [{ type: "JSXExpressionContainer", expression: { type: "Identifier", name: "myVar" } }] + } as any; + expect(hasTextContentChild(node)).toBe(true); + }); + + it("should return false when node.children has JSXExpressionContainer with an empty string literal", () => { + const node: TSESTree.JSXElement = { + children: [{ type: "JSXExpressionContainer", expression: { type: "Literal", value: "" } }] + } as any; + expect(hasTextContentChild(node)).toBe(false); + }); });