From 81c9dad6964de41e5775872f6dd26bf988cd2989 Mon Sep 17 00:00:00 2001
From: adamviktora <84135613+adamviktora@users.noreply.github.com>
Date: Thu, 26 Sep 2024 17:27:19 +0200
Subject: [PATCH] feat(EmptyState): make titleText optional (#770)
* feat(EmptyState): make titleText optional
* refactor (PR review)
* refactor no.2
---
.../emptyStateHeader-move-into-emptyState.md | 3 -
...tyStateHeader-move-into-emptyState.test.ts | 50 ++++----------
.../emptyStateHeader-move-into-emptyState.ts | 65 +++++--------------
...mptyStateHeaderMoveIntoEmptyStateInput.tsx | 17 +++++
...ptyStateHeaderMoveIntoEmptyStateOutput.tsx | 12 ++++
5 files changed, 60 insertions(+), 87 deletions(-)
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.md b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.md
index 95d61eae7..152574d9c 100644
--- a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.md
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.md
@@ -2,8 +2,6 @@
EmptyStateHeader and EmptyStateIcon are now rendered internally within EmptyState and should only be customized using props. Content passed to the `icon` prop on EmptyState will also be wrapped by EmptyStateIcon automatically.
-Additionally, the `titleText` prop is now required on EmptyState.
-
#### Examples
In:
@@ -17,4 +15,3 @@ Out:
```jsx
%outputExample%
```
-
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.test.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.test.ts
index 278e05ac1..5f18c4910 100644
--- a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.test.ts
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.test.ts
@@ -15,6 +15,10 @@ ruleTester.run("emptyStateHeader-move-into-emptyState", rule, {
{
code: `import { EmptyState } from '@patternfly/react-core'; `,
},
+ {
+ // without an EmptyStateHeader or Title text
+ code: `import { EmptyState } from "@patternfly/react-core"; Foo bar`,
+ },
],
invalid: [
{
@@ -106,14 +110,13 @@ ruleTester.run("emptyStateHeader-move-into-emptyState", rule, {
} from "@patternfly/react-core";
export const EmptyStateHeaderMoveIntoEmptyStateInput = () => (
-
-
-
+
+
);
`,
errors: [
{
- message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props, and the titleText prop is now required on EmptyState. You must manually supply a titleText prop to EmptyState, then you can rerun this codemod.`,
+ message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props.`,
type: "JSXElement",
},
],
@@ -143,7 +146,7 @@ ruleTester.run("emptyStateHeader-move-into-emptyState", rule, {
`,
errors: [
{
- message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props, and the titleText prop is now required on EmptyState.`,
+ message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props.`,
type: "JSXElement",
},
],
@@ -175,7 +178,7 @@ ruleTester.run("emptyStateHeader-move-into-emptyState", rule, {
`,
errors: [
{
- message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props, and the titleText prop is now required on EmptyState.`,
+ message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props.`,
type: "JSXElement",
},
],
@@ -211,7 +214,7 @@ ruleTester.run("emptyStateHeader-move-into-emptyState", rule, {
`,
errors: [
{
- message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props, and the titleText prop is now required on EmptyState.`,
+ message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props.`,
type: "JSXElement",
},
],
@@ -249,32 +252,7 @@ ruleTester.run("emptyStateHeader-move-into-emptyState", rule, {
`,
errors: [
{
- message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props, and the titleText prop is now required on EmptyState.`,
- type: "JSXElement",
- },
- ],
- },
- {
- // without an EmptyStateHeader or titleText
- code: `import { EmptyState } from "@patternfly/react-core";
-
- export const EmptyStateHeaderMoveIntoEmptyStateInput = () => (
-
- Foo bar
-
- );
- `,
- output: `import { EmptyState } from "@patternfly/react-core";
-
- export const EmptyStateHeaderMoveIntoEmptyStateInput = () => (
-
- Foo bar
-
- );
- `,
- errors: [
- {
- message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props, and the titleText prop is now required on EmptyState. You must manually supply a titleText prop to EmptyState`,
+ message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props.`,
type: "JSXElement",
},
],
@@ -489,7 +467,7 @@ ruleTester.run("emptyStateHeader-move-into-emptyState", rule, {
`,
errors: [
{
- message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props, and the titleText prop is now required on EmptyState.`,
+ message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props.`,
type: "JSXElement",
},
],
@@ -540,7 +518,7 @@ ruleTester.run("emptyStateHeader-move-into-emptyState", rule, {
type: "JSXElement",
},
{
- message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props, and the titleText prop is now required on EmptyState. Additionally, the EmptyStateIcon component now wraps content passed to the icon prop automatically.`,
+ message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props. Additionally, the EmptyStateIcon component now wraps content passed to the icon prop automatically.`,
type: "JSXElement",
},
],
@@ -587,7 +565,7 @@ ruleTester.run("emptyStateHeader-move-into-emptyState", rule, {
type: "JSXElement",
},
{
- message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props, and the titleText prop is now required on EmptyState. Additionally, the EmptyStateIcon component now wraps content passed to the icon prop automatically.`,
+ message: `EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props. Additionally, the EmptyStateIcon component now wraps content passed to the icon prop automatically.`,
type: "JSXElement",
},
],
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.ts
index 67fe9e1ea..de091b73f 100644
--- a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.ts
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeader-move-into-emptyState.ts
@@ -17,6 +17,7 @@ import {
getFromPackage,
getChildrenAsAttributeValueText,
getRemoveElementFixes,
+ childrenIsEmpty,
} from "../../helpers";
// https://github.com/patternfly/patternfly-react/pull/9947
@@ -26,29 +27,11 @@ const composeMessage = (
hasChildren?: boolean
) => {
let message =
- "EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props";
- const missingTitleTextMessage =
- ", and the titleText prop is now required on EmptyState.";
-
- if (hasTitleText) {
- message += ".";
- } else {
- message += missingTitleTextMessage;
- }
+ "EmptyStateHeader has been moved inside of the EmptyState component and is now only customizable using props.";
if (hasTitleText && hasChildren) {
message +=
- " Because the children for EmptyStateHeader are now inaccessible you must remove either the children or the titleText prop";
- } else if (!hasTitleText && !hasChildren) {
- message += " You must manually supply a titleText prop to EmptyState";
- }
-
- const hasHeader = [hasTitleText, hasIcon, hasChildren].some(
- (arg) => typeof arg !== "undefined"
- );
-
- if (hasTitleText === hasChildren && hasHeader) {
- message += ", then you can rerun this codemod.";
+ " Because the children for EmptyStateHeader are now inaccessible you must remove either the children or the titleText prop, then you can rerun this codemod.";
}
if (hasIcon) {
@@ -175,19 +158,6 @@ module.exports = {
const titleChild = getChildJSXElementByName(node, "Title");
- if (
- (!header || header.type !== "JSXElement") &&
- (!titleChild || titleChild.type !== "JSXElement")
- ) {
- // report without fixer if there is no header/title or the header/title is not a React element, because
- // creating a titleText for the EmptyState in this case is difficult
- context.report({
- node,
- message: composeMessage(),
- });
- return;
- }
-
const newEmptyStateProps: string[] = [];
const removeElements: JSXElement[] = [];
@@ -204,6 +174,10 @@ module.exports = {
"EmptyStateIcon"
);
+ if (!header && !titleChild && !emptyStateIconChild) {
+ return;
+ }
+
let iconProp: string = "";
if (emptyStateIconChild) {
@@ -231,19 +205,12 @@ module.exports = {
hasTitleText = !!titleTextAttribute;
hasIcon ||= !!headerIconAttribute;
- hasChildren ||= header.children.length > 0;
+ hasChildren ||= !childrenIsEmpty(header.children);
const message = composeMessage(hasTitleText, hasIcon, hasChildren);
- if (!titleTextAttribute && !hasChildren) {
- // report without fixer if there is a header, but it doesn't have titleText or children, because creating a
- // titleText for the EmptyState in this case is difficult
- context.report({ node, message });
- return;
- }
-
if (titleTextAttribute && hasChildren) {
- // report without fixer if there is the header has a titleText and children, because creating an accessible
+ // report without fixer if the header has both titleText and children, because creating an accessible
// titleText for the EmptyState in this case is difficult
context.report({ node, message });
return;
@@ -267,12 +234,14 @@ module.exports = {
titleTextAttribute
);
- const titleText =
- titleTextPropValue ||
- `titleText=${getChildrenAsAttributeValueText(
- context,
- header.children
- )}`;
+ const childrenTitleText = hasChildren
+ ? `titleText=${getChildrenAsAttributeValueText(
+ context,
+ header.children
+ )}`
+ : "";
+
+ const titleText = titleTextPropValue || childrenTitleText;
const iconPropValue = getExpression(headerIconAttribute?.value);
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeaderMoveIntoEmptyStateInput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeaderMoveIntoEmptyStateInput.tsx
index 04605a858..ef8915e31 100644
--- a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeaderMoveIntoEmptyStateInput.tsx
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeaderMoveIntoEmptyStateInput.tsx
@@ -26,3 +26,20 @@ export const EmptyStateWithoutHeaderMoveIntoEmptyStateInput = () => (
Body
);
+
+export const EmptyStateHeaderWithoutTitleTextMoveIntoEmptyStateInput = () => (
+
+ }
+ />
+
+);
+
+export const EmptyStateWithoutHeaderAndTitleTextMoveIntoEmptyStateInput =
+ () => (
+
+
+ Body
+
+ );
diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeaderMoveIntoEmptyStateOutput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeaderMoveIntoEmptyStateOutput.tsx
index 1d4f3f451..1902bb642 100644
--- a/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeaderMoveIntoEmptyStateOutput.tsx
+++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/emptyStateHeaderMoveIntoEmptyState/emptyStateHeaderMoveIntoEmptyStateOutput.tsx
@@ -19,3 +19,15 @@ export const EmptyStateWithoutHeaderMoveIntoEmptyStateInput = () => (
Body
);
+
+export const EmptyStateHeaderWithoutTitleTextMoveIntoEmptyStateInput = () => (
+
+
+);
+
+export const EmptyStateWithoutHeaderAndTitleTextMoveIntoEmptyStateInput =
+ () => (
+
+ Body
+
+ );