diff --git a/frontend/__tests__/components/utils/page-heading.spec.tsx b/frontend/__tests__/components/utils/page-heading.spec.tsx index 3c35087f566..293202daa39 100644 --- a/frontend/__tests__/components/utils/page-heading.spec.tsx +++ b/frontend/__tests__/components/utils/page-heading.spec.tsx @@ -1,84 +1,105 @@ -import { Link } from 'react-router-dom-v5-compat'; -import { shallow, ShallowWrapper } from 'enzyme'; - -import PrimaryHeading from '@console/shared/src/components/heading/PrimaryHeading'; +import { configure, render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom'; import { PageHeading, - PageHeadingProps, BreadCrumbs, BreadCrumbsProps, } from '../../../public/components/utils/headings'; -import { ResourceIcon } from '../../../public/components/utils'; import { testResourceInstance } from '../../../__mocks__/k8sResourcesMocks'; +import { MemoryRouter } from 'react-router-dom-v5-compat'; + +// Mock getRootNode +Object.defineProperty(Element.prototype, 'getRootNode', { + value: function () { + let rootNode = this; + while (rootNode.parentNode) { + rootNode = rootNode.parentNode; + } + return rootNode; + }, + configurable: true, +}); describe(BreadCrumbs.displayName, () => { - let wrapper: ShallowWrapper; let breadcrumbs: BreadCrumbsProps['breadcrumbs']; beforeEach(() => { + configure({ testIdAttribute: 'data-test' }); + breadcrumbs = [ { name: 'pods', path: '/pods' }, - { name: 'containers', path: '/pods' }, + { name: 'containers', path: '/pods/containers' }, ]; - wrapper = shallow(); }); it('renders each given breadcrumb', () => { - const links: ShallowWrapper = wrapper.find(Link); - const nonLink: ShallowWrapper = wrapper.findWhere( - (BreadcrumbItem) => BreadcrumbItem.props().isActive === true, + render( + + + , ); - expect(links.length + nonLink.length).toEqual(breadcrumbs.length); - - breadcrumbs.forEach((crumb, i) => { - if (i < links.length) { - expect(links.at(i).props().to).toEqual(crumb.path); - expect(links.at(i).childAt(0).text()).toEqual(crumb.name); + breadcrumbs.forEach((crumb) => { + if (crumb.path) { + const link = screen.getByRole('link', { name: crumb.name }); + expect(link).toHaveAttribute('href', crumb.path); } else { - expect(nonLink.render().text()).toEqual(crumb.name); + expect(screen.getByText(crumb.name)).toBeInTheDocument(); } }); }); }); describe(PageHeading.displayName, () => { - let wrapper: ShallowWrapper; - beforeEach(() => { - wrapper = shallow(); + configure({ testIdAttribute: 'data-test' }); }); it('renders resource icon if given `kind`', () => { const kind = 'Pod'; - wrapper.setProps({ kind }); - const icon = wrapper.find(ResourceIcon); + render( + + + , + ); - expect(icon.exists()).toBe(true); - expect(icon.props().kind).toEqual(kind); + const icon = screen.getByTitle(kind); + expect(icon).toBeInTheDocument(); + expect(screen.getByText(kind)).toBeInTheDocument(); }); it('renders custom title component if given', () => { const title = My Custom Title; - wrapper.setProps({ title }); + render( + + + , + ); - expect(wrapper.find(PrimaryHeading).contains(title)).toBe(true); + expect(screen.getByText('My Custom Title')).toBeInTheDocument(); }); it('renders breadcrumbs if given `breadcrumbsFor` function', () => { const breadcrumbs = []; - wrapper = wrapper.setProps({ - breadcrumbsFor: () => breadcrumbs, - obj: { data: testResourceInstance, loaded: true, loadError: null }, - }); + render( + + breadcrumbs} + /> + , + ); - expect(wrapper.find(BreadCrumbs).exists()).toBe(true); - expect(wrapper.find(BreadCrumbs).props().breadcrumbs).toEqual(breadcrumbs); + expect(screen.getByTestId('page-heading-breadcrumbs')).toBeInTheDocument(); }); it('does not render breadcrumbs if object has not loaded', () => { - wrapper = wrapper.setProps({ breadcrumbsFor: () => [], obj: null }); + render( + + []} /> + , + ); - expect(wrapper.find(BreadCrumbs).exists()).toBe(false); + expect(screen.queryByTestId('page-heading-breadcrumbs')).not.toBeInTheDocument(); }); }); diff --git a/frontend/packages/dev-console/src/components/import/jar/UploadJarPage.tsx b/frontend/packages/dev-console/src/components/import/jar/UploadJarPage.tsx index 26e709afb75..6369fca1dc2 100644 --- a/frontend/packages/dev-console/src/components/import/jar/UploadJarPage.tsx +++ b/frontend/packages/dev-console/src/components/import/jar/UploadJarPage.tsx @@ -50,9 +50,10 @@ const UploadJarPage: React.FunctionComponent = () => { return ( {t('devconsole~Upload JAR file')} - - {t('devconsole~Upload a JAR file from your local desktop to OpenShift')} - + {(desiredApplication) => ( = ({ - - - { - "Project access allows you to add or remove a user's access to the project. More advanced management of role-based access control appear in " - } - Roles and{' '} - Role Bindings. - - - {!isManaged() && ( - - - {' '} - For more information, see the{' '} - role-based access control documentation. - - - )} - + helpText={ + <> + + + { + "Project access allows you to add or remove a user's access to the project. More advanced management of role-based access control appear in " + } + Roles and{' '} + Role Bindings. + + {!isManaged() && ( + + {' '} + For more information, see the{' '} + + role-based access control documentation + + . + + )} + + + } + /> {roleBindings.loadError ? ( ) : ( diff --git a/frontend/packages/dev-console/src/components/projects/ProjectListPage.tsx b/frontend/packages/dev-console/src/components/projects/ProjectListPage.tsx index afa11cd5ff6..d3d1a0ac5c7 100644 --- a/frontend/packages/dev-console/src/components/projects/ProjectListPage.tsx +++ b/frontend/packages/dev-console/src/components/projects/ProjectListPage.tsx @@ -7,22 +7,18 @@ import './ProjectListPage.scss'; export type ProjectListPageProps = { title: string; listComponent?: React.ComponentType; - children?: React.ReactNode; badge?: React.ReactNode; helpText?: React.ReactNode; }; -const ProjectListPage: React.FC = ({ +const ProjectListPage: React.FCC = ({ badge, title, - children, listComponent, helpText, ...listPageProps }) => (
- - {children} - + { return ( {t('knative-plugin~Event Sink')} - - {t( + + /> {loaded && isValidSink && !createSinkAccessLoading && createSinkAccess ? ( { return ( {t('knative-plugin~Event Source')} - - {t( + + /> {loaded ? ( { return ( {t('knative-plugin~Broker')} - - {t( + + /> {(selectedApplication) => ( { return ( {t('knative-plugin~Channel')} - - {t( + + /> { return ( {t('knative-plugin~Subscribe')} - - {t('knative-plugin~Subscribe to')} {subscribeApiVersion} {subscribeKind} {namespace}/ - {subscribeName} - + + {t('knative-plugin~Subscribe to')} {subscribeApiVersion} {subscribeKind} {namespace}/ + {subscribeName} + + } + /> ); diff --git a/frontend/packages/knative-plugin/src/components/knatify/CreateKnatifyPage.tsx b/frontend/packages/knative-plugin/src/components/knatify/CreateKnatifyPage.tsx index b910eb09f0d..0fa55f37233 100644 --- a/frontend/packages/knative-plugin/src/components/knatify/CreateKnatifyPage.tsx +++ b/frontend/packages/knative-plugin/src/components/knatify/CreateKnatifyPage.tsx @@ -119,11 +119,10 @@ const CreateKnatifyPage: React.FunctionComponent = () => { - {t( + helpText={t( 'knative-plugin~This feature will create a new serverless deployment next to your existing deployment. Other configurations, including the traffic pattern, can be modified in the form.', )} - + /> {isResourceLoaded ? ( = (props) => { } }; - const breadcrumbClicked = (e: React.MouseEvent, i: number) => { + const breadcrumbClicked = (e: React.MouseEvent, i: number) => { e.preventDefault(); setDrilldownHistory(_.take(drilldownHistory, i)); }; @@ -114,23 +114,12 @@ export const ExploreType: React.FC = (props) => { return ( <> {!_.isEmpty(breadcrumbs) && ( - + {breadcrumbs.map((crumb, i) => { const isLast = i === breadcrumbs.length - 1; return ( - - {isLast ? ( - crumb - ) : ( - - )} + breadcrumbClicked(e, i)}> + {crumb} ); })} diff --git a/frontend/public/components/utils/details-item.tsx b/frontend/public/components/utils/details-item.tsx index 4464fd36873..d90b6652b55 100644 --- a/frontend/public/components/utils/details-item.tsx +++ b/frontend/public/components/utils/details-item.tsx @@ -22,7 +22,7 @@ export const PropertyPath: React.FC<{ kind: string; path: string | string[] }> = }) => { const pathArray: string[] = _.toPath(path); return ( - + {kind} {pathArray.map((property, i) => { const isLast = i === pathArray.length - 1; diff --git a/frontend/public/components/utils/headings.tsx b/frontend/public/components/utils/headings.tsx index 55d413fde94..3f7746350dc 100644 --- a/frontend/public/components/utils/headings.tsx +++ b/frontend/public/components/utils/headings.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import classNames from 'classnames'; import * as _ from 'lodash-es'; -import { Link } from 'react-router-dom-v5-compat'; import { useTranslation } from 'react-i18next'; import { ActionList, @@ -24,6 +23,7 @@ import PrimaryHeading from '@console/shared/src/components/heading/PrimaryHeadin import SecondaryHeading from '@console/shared/src/components/heading/SecondaryHeading'; import { FavoriteButton } from '@console/app/src/components/favorite/FavoriteButton'; import NavTitle from '@console/shared/src/components/layout/NavTitle'; +import { LinkTo } from '@console/shared/src/components/links/LinkTo'; import { ActionsMenu, FirehoseResult, KebabOption, ResourceIcon } from './index'; import { connectToModel } from '../../kinds'; @@ -39,24 +39,18 @@ export const ResourceItemDeleting = () => { ); }; -export const BreadCrumbs: React.SFC = ({ breadcrumbs }) => ( - +export const BreadCrumbs: React.FCC = ({ breadcrumbs }) => ( + {breadcrumbs.map((crumb, i, { length }) => { - const isLast = i === length - 1; - return ( - - {isLast ? ( - crumb.name - ) : ( - - {crumb.name} - - )} + + {crumb.name} ); })} diff --git a/frontend/public/style/_common.scss b/frontend/public/style/_common.scss index f2a1eaea4b0..ae3f32e87ea 100644 --- a/frontend/public/style/_common.scss +++ b/frontend/public/style/_common.scss @@ -22,10 +22,6 @@ $co-icon-arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/20 width: 12px; } -.co-breadcrumb { - padding-bottom: var(--pf-t--global--spacer--sm); -} - .co-divider { margin-bottom: var(--pf-t--global--spacer--lg); margin-top: var(--pf-t--global--spacer--lg);