From 722b9e617ba52632c8d6a5337909e6942a8e00c0 Mon Sep 17 00:00:00 2001 From: Eric Olkowski <70952936+thatblindgeye@users.noreply.github.com> Date: Mon, 2 Sep 2024 02:47:16 -0400 Subject: [PATCH] fix(LoginPage): updated markup for LoginMainHeader (#752) * fix(LoginPage): updated markup for LoginMainHeader * Added description to importdec matches helper * PR feedback * Updated import declaration to return boolean --------- Co-authored-by: adamviktora <84135613+adamviktora@users.noreply.github.com> --- .../src/ruleCustomization.ts | 1 + .../src/rules/helpers/index.ts | 3 +- .../checkMatchingImportDeclaration.ts | 30 ++++++ .../checkMatchingJSXOpeningElement.ts} | 1 + .../src/rules/helpers/pfPackageMatches.ts | 1 + .../loginMainHeader-warn-updated-markup.md | 3 + ...oginMainHeader-warn-updated-markup.test.ts | 91 +++++++++++++++++++ .../loginMainHeader-warn-updated-markup.ts | 35 +++++++ .../loginMainHeaderWarnUpdatedMarkupInput.tsx | 8 ++ ...loginMainHeaderWarnUpdatedMarkupOutput.tsx | 8 ++ 10 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingImportDeclaration.ts rename packages/eslint-plugin-pf-codemods/src/rules/helpers/{nodeMatches.ts => nodeMatches/checkMatchingJSXOpeningElement.ts} (83%) create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.md create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.test.ts create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.ts create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeaderWarnUpdatedMarkupInput.tsx create mode 100644 packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeaderWarnUpdatedMarkupOutput.tsx diff --git a/packages/eslint-plugin-pf-codemods/src/ruleCustomization.ts b/packages/eslint-plugin-pf-codemods/src/ruleCustomization.ts index 662bbc3c6..487f2cb0a 100644 --- a/packages/eslint-plugin-pf-codemods/src/ruleCustomization.ts +++ b/packages/eslint-plugin-pf-codemods/src/ruleCustomization.ts @@ -27,6 +27,7 @@ export const warningRules = [ "horizontalSubnav-warn-ariaLabel", "jumpLinksItem-warn-markup-change", "label-warn-truncated-default", + "loginMainHeader-warn-updated-markup", "logViewer-moved-styles", "menuItemAction-warn-update-markup", "menuToggle-warn-iconOnly-toggle", diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts index e719e884d..314f1deb5 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/index.ts @@ -24,7 +24,8 @@ export * from "./interfaces"; export * from "./isReactIcon"; export * from "./JSXAttributes"; export * from "./makeJSXElementSelfClosing"; -export * from "./nodeMatches"; +export * from "./nodeMatches/checkMatchingImportDeclaration"; +export * from "./nodeMatches/checkMatchingJSXOpeningElement"; export * from "./pfPackageMatches"; export * from "./removeElement"; export * from "./removeEmptyLineAfter"; diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingImportDeclaration.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingImportDeclaration.ts new file mode 100644 index 000000000..848497b83 --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingImportDeclaration.ts @@ -0,0 +1,30 @@ +import { ImportDeclaration, ImportSpecifier } from "estree-jsx"; +import { pfPackageMatches } from "../pfPackageMatches"; + +function checkSpecifierExists( + node: ImportDeclaration, + importSpecifier: ImportSpecifier +) { + return node.specifiers.some( + (specifier) => + specifier.type === "ImportSpecifier" && + specifier.imported.name === importSpecifier.imported.name + ); +} + +/** Used to check whether the current ImportDeclaration node matches at least 1 of the import specifiers. */ +export function checkMatchingImportDeclaration( + node: ImportDeclaration, + imports: ImportSpecifier | ImportSpecifier[], + packageName: string = "@patternfly/react-core" +) { + if (!pfPackageMatches(packageName, node.source.value)) { + return false; + } + + if (Array.isArray(imports)) { + return imports.some((imp) => checkSpecifierExists(node, imp)); + } + + return checkSpecifierExists(node, imports); +} diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingJSXOpeningElement.ts similarity index 83% rename from packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches.ts rename to packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingJSXOpeningElement.ts index 1d3657947..0863a56b1 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches.ts +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/nodeMatches/checkMatchingJSXOpeningElement.ts @@ -4,6 +4,7 @@ import { ImportDefaultSpecifier, } from "estree-jsx"; +/** Used to check whether the current JSXOpeningElement node matches at least 1 of the import specifiers. */ export function checkMatchingJSXOpeningElement( node: JSXOpeningElement, imports: diff --git a/packages/eslint-plugin-pf-codemods/src/rules/helpers/pfPackageMatches.ts b/packages/eslint-plugin-pf-codemods/src/rules/helpers/pfPackageMatches.ts index e60b8d21f..f6889abd7 100644 --- a/packages/eslint-plugin-pf-codemods/src/rules/helpers/pfPackageMatches.ts +++ b/packages/eslint-plugin-pf-codemods/src/rules/helpers/pfPackageMatches.ts @@ -1,5 +1,6 @@ import { ImportDeclaration } from "estree-jsx"; +// TODO: Swap the params so that packageName has a default value of pf/react-core and can be optional export function pfPackageMatches( packageName: string, nodeSrc: ImportDeclaration["source"]["value"] diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.md b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.md new file mode 100644 index 000000000..b0a39161d --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.md @@ -0,0 +1,3 @@ +### loginMainHeader-warn-updated-markup [(#10880)](https://github.com/patternfly/patternfly-react/pull/10880) + +The markup for LoginMainHeader - which is used internally within LoginPage - has been updated, now using a `div` wrapper instead of a `header` element wrapper. diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.test.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.test.ts new file mode 100644 index 000000000..9ffcb28d7 --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.test.ts @@ -0,0 +1,91 @@ +const ruleTester = require("../../ruletester"); +import * as rule from "./loginMainHeader-warn-updated-markup"; + +ruleTester.run("loginMainHeader-warn-updated-markup", rule, { + valid: [ + { + code: ``, + }, + { + code: `import { LoginMainHeader } from 'somewhere-else'`, + }, + { + code: ``, + }, + { + code: `import { LoginPage } from 'somewhere-else'`, + }, + ], + invalid: [ + { + code: `import { LoginMainHeader } from '@patternfly/react-core';`, + output: `import { LoginMainHeader } from '@patternfly/react-core';`, + errors: [ + { + message: `The markup for LoginMainHeader has been updated, now using a div wrapper instead of a header element wrapper.`, + type: "ImportDeclaration", + }, + ], + }, + { + code: `import { LoginPage } from '@patternfly/react-core';`, + output: `import { LoginPage } from '@patternfly/react-core';`, + errors: [ + { + message: `The markup for LoginMainHeader (which is used internally within LoginPage) has been updated, now using a div wrapper instead of a header element wrapper.`, + type: "ImportDeclaration", + }, + ], + }, + { + code: `import { LoginPage, LoginMainHeader, Button } from '@patternfly/react-core';`, + output: `import { LoginPage, LoginMainHeader, Button } from '@patternfly/react-core';`, + errors: [ + { + message: `The markup for LoginMainHeader (which is used internally within LoginPage) has been updated, now using a div wrapper instead of a header element wrapper.`, + type: "ImportDeclaration", + }, + ], + }, + { + code: `import { LoginMainHeader as CustomThing } from '@patternfly/react-core';`, + output: `import { LoginMainHeader as CustomThing } from '@patternfly/react-core';`, + errors: [ + { + message: `The markup for LoginMainHeader has been updated, now using a div wrapper instead of a header element wrapper.`, + type: "ImportDeclaration", + }, + ], + }, + { + code: `import { LoginMainHeader } from '@patternfly/react-core/dist/esm/components/LoginPage/index.js';`, + output: `import { LoginMainHeader } from '@patternfly/react-core/dist/esm/components/LoginPage/index.js';`, + errors: [ + { + message: `The markup for LoginMainHeader has been updated, now using a div wrapper instead of a header element wrapper.`, + type: "ImportDeclaration", + }, + ], + }, + { + code: `import { LoginMainHeader } from '@patternfly/react-core/dist/js/components/LoginPage/index.js';`, + output: `import { LoginMainHeader } from '@patternfly/react-core/dist/js/components/LoginPage/index.js';`, + errors: [ + { + message: `The markup for LoginMainHeader has been updated, now using a div wrapper instead of a header element wrapper.`, + type: "ImportDeclaration", + }, + ], + }, + { + code: `import { LoginMainHeader } from '@patternfly/react-core/dist/dynamic/components/LoginPage/index.js';`, + output: `import { LoginMainHeader } from '@patternfly/react-core/dist/dynamic/components/LoginPage/index.js';`, + errors: [ + { + message: `The markup for LoginMainHeader has been updated, now using a div wrapper instead of a header element wrapper.`, + type: "ImportDeclaration", + }, + ], + }, + ], +}); diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.ts b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.ts new file mode 100644 index 000000000..e3d4479ec --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeader-warn-updated-markup.ts @@ -0,0 +1,35 @@ +import { Rule } from "eslint"; +import { ImportDeclaration } from "estree-jsx"; +import { getFromPackage, checkMatchingImportDeclaration } from "../../helpers"; + +// https://github.com/patternfly/patternfly-react/pull/10880 +module.exports = { + meta: {}, + create: function (context: Rule.RuleContext) { + const basePackage = "@patternfly/react-core"; + const { imports: loginImports } = getFromPackage(context, basePackage, [ + "LoginPage", + "LoginMainHeader", + ]); + + return !loginImports.length + ? {} + : { + ImportDeclaration(node: ImportDeclaration) { + if (checkMatchingImportDeclaration(node, loginImports)) { + const hasLoginPageImport = loginImports.find( + (imp) => imp.imported.name === "LoginPage" + ); + context.report({ + node, + message: `The markup for LoginMainHeader${ + hasLoginPageImport + ? " (which is used internally within LoginPage)" + : "" + } has been updated, now using a div wrapper instead of a header element wrapper.`, + }); + } + }, + }; + }, +}; diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeaderWarnUpdatedMarkupInput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeaderWarnUpdatedMarkupInput.tsx new file mode 100644 index 000000000..5b5c377cf --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeaderWarnUpdatedMarkupInput.tsx @@ -0,0 +1,8 @@ +import { LoginMainHeader, LoginPage } from "@patternfly/react-core"; + +export const LoginMainHeaderWarnUpdatedMarkupInput = () => ( + <> + + + +); diff --git a/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeaderWarnUpdatedMarkupOutput.tsx b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeaderWarnUpdatedMarkupOutput.tsx new file mode 100644 index 000000000..5b5c377cf --- /dev/null +++ b/packages/eslint-plugin-pf-codemods/src/rules/v6/loginMainHeaderWarnUpdatedMarkup/loginMainHeaderWarnUpdatedMarkupOutput.tsx @@ -0,0 +1,8 @@ +import { LoginMainHeader, LoginPage } from "@patternfly/react-core"; + +export const LoginMainHeaderWarnUpdatedMarkupInput = () => ( + <> + + + +);