Skip to content

Commit

Permalink
Improve OUIA id's in current components (#131)
Browse files Browse the repository at this point in the history
* Improve ouiaIds in Ansible

* Improve ouiaIds in Battery

* Improve ouiaIds in CloseButton

* Improve ouiaIds in Error components

* Improve ouiaIds in state components

* Improve ouiaIds in Shortcut

* Improve ouiaIds in WarningModal

* Improve ouiaIds in SkeletonTable

* Improve ouiaIds in MultiContentCard

* feat(ouia): Improve ouiaIds in LogSnippet & TagCount

* Update the contribution guide
  • Loading branch information
fhlavac authored Apr 18, 2024
1 parent 625ced5 commit fec3374
Show file tree
Hide file tree
Showing 29 changed files with 387 additions and 154 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ When adding/making changes to a component, always make sure your code is tested:
- use React Testing Library for testing
- add tests to a `[ComponentName].test.tsx` file to your component's directory
- make sure all the core logic is covered
- add `ouiaId` to component props definition with a default value of the component name (for subcomponents, let's use `ComponentName-element-specification` naming convention e.g. `ouiaId="WarningModal-confirm-button"`)

### Styling:
- for styling always use JSS
Expand Down
8 changes: 5 additions & 3 deletions packages/module/src/Ansible/Ansible.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { createUseStyles } from 'react-jss';
export interface AnsibleProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> {
/** Supported/unsupported variant flag */
unsupported?: boolean | number;
/** Ansible icon className*/
/** Ansible icon className */
className?: string;
/** Custom OUIA ID */
ouiaId?: string | number;
}

const useStyles = createUseStyles({
Expand All @@ -30,7 +32,7 @@ const useStyles = createUseStyles({
}
})

const Ansible: React.FunctionComponent<AnsibleProps> = ({ unsupported, className, ...props }: AnsibleProps) => {
const Ansible: React.FunctionComponent<AnsibleProps> = ({ unsupported, className, ouiaId = "Ansible-icon", ...props }: AnsibleProps) => {
const classes = useStyles();
const ansibleLogoClass = clsx(
classes.ansible,
Expand Down Expand Up @@ -71,7 +73,7 @@ const Ansible: React.FunctionComponent<AnsibleProps> = ({ unsupported, className
);

return (
<i className={ansibleLogoClass} title={unsupported ? "Ansible is not supported" : "Ansible supported" }{...props}>
<i className={ansibleLogoClass} title={unsupported ? "Ansible is not supported" : "Ansible supported" } data-ouia-component-id={ouiaId} {...props}>
<svg
version="1.1"
x="0px"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ exports[`Ansible component should render supported - boolean 1`] = `
<div>
<i
class="ansible-0-2-1 ansibleSupported-0-2-2"
data-ouia-component-id="Ansible-icon"
title="Ansible supported"
>
<svg
Expand All @@ -29,6 +30,7 @@ exports[`Ansible component should render supported - number 1`] = `
<div>
<i
class="ansible-0-2-1 ansibleSupported-0-2-2"
data-ouia-component-id="Ansible-icon"
title="Ansible supported"
>
<svg
Expand All @@ -54,6 +56,7 @@ exports[`Ansible component should render unsupported - boolean 1`] = `
<div>
<i
class="ansible-0-2-1 ansibleUnsupported-0-2-3"
data-ouia-component-id="Ansible-icon"
title="Ansible is not supported"
>
<svg
Expand Down Expand Up @@ -103,6 +106,7 @@ exports[`Ansible component should render unsupported - number 1`] = `
<div>
<i
class="ansible-0-2-1 ansibleUnsupported-0-2-3"
data-ouia-component-id="Ansible-icon"
title="Ansible is not supported"
>
<svg
Expand Down
6 changes: 4 additions & 2 deletions packages/module/src/Battery/Battery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,11 @@ export interface BatteryProps extends React.DetailedHTMLProps<React.HTMLAttribut
labelHidden?: boolean;
/** Custom className */
className?: string;
/** Custom OUIA ID */
ouiaId?: string | number;
}

const Battery: React.FunctionComponent<BatteryProps> = ({ severity, label, labelHidden, className, ...props }: BatteryProps) => {
const Battery: React.FunctionComponent<BatteryProps> = ({ severity, label, labelHidden, className, ouiaId = 'Battery-icon', ...props }: BatteryProps) => {
const classes = useStyles();
const batteryClasses = clsx(classes.battery, classes[String(batteryLevels(severity, true))], className);

Expand All @@ -103,7 +105,7 @@ const Battery: React.FunctionComponent<BatteryProps> = ({ severity, label, label
return (
<React.Fragment>
{/* eslint-disable-next-line react/no-unknown-property */}
<i className={batteryClasses} {...title} {...props} widget-type="Battery" widget-id={label}>
<i className={batteryClasses} {...title} {...props} widget-type="Battery" widget-id={label} data-ouia-component-id={ouiaId}>
<svg
version="1.1"
x="0px"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ exports[`Battery component API should hide label 1`] = `
<div>
<i
class="battery-0-2-1 batteryHigh-0-2-5"
data-ouia-component-id="Battery-icon"
title="high high"
widget-id="high"
widget-type="Battery"
Expand Down Expand Up @@ -32,6 +33,7 @@ exports[`Battery component should render correctly CriticalBattery 1`] = `
<div>
<i
class="battery-0-2-1 batteryCritical-0-2-6"
data-ouia-component-id="Battery-icon"
title="critical Critical"
widget-id="Critical"
widget-type="Battery"
Expand Down Expand Up @@ -65,6 +67,7 @@ exports[`Battery component should render correctly HighBattery 1`] = `
<div>
<i
class="battery-0-2-1 batteryHigh-0-2-5"
data-ouia-component-id="Battery-icon"
title="high High"
widget-id="High"
widget-type="Battery"
Expand Down Expand Up @@ -98,6 +101,7 @@ exports[`Battery component should render correctly LowBattery 1`] = `
<div>
<i
class="battery-0-2-1 batteryLow-0-2-3"
data-ouia-component-id="Battery-icon"
title="low Low"
widget-id="Low"
widget-type="Battery"
Expand Down Expand Up @@ -131,6 +135,7 @@ exports[`Battery component should render correctly MediumBattery 1`] = `
<div>
<i
class="battery-0-2-1 batteryMedium-0-2-4"
data-ouia-component-id="Battery-icon"
title="medium Medium"
widget-id="Medium"
widget-type="Battery"
Expand Down Expand Up @@ -164,6 +169,7 @@ exports[`Battery component should render correctly NullBatery, default 1`] = `
<div>
<i
class="battery-0-2-1 batteryDefault-0-2-2"
data-ouia-component-id="Battery-icon"
title=" "
widget-id=""
widget-type="Battery"
Expand Down
2 changes: 2 additions & 0 deletions packages/module/src/CloseButton/CloseButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const CloseButton: React.FunctionComponent<CloseButtonProps> = ({
className,
dataTestID,
onClick,
ouiaId="CloseButton",
...props
}: CloseButtonProps) => {
const classes = useStyles();
Expand All @@ -30,6 +31,7 @@ const CloseButton: React.FunctionComponent<CloseButtonProps> = ({
data-test-id={dataTestID}
onClick={onClick}
variant={ButtonVariant.plain}
ouiaId={ouiaId}
{...props}
>
<CloseIcon />
Expand Down
25 changes: 15 additions & 10 deletions packages/module/src/ErrorBoundary/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface ErrorPageProps {
defaultErrorDescription?: React.ReactNode;
/** The component that the error boundary component is wrapped around, which should be returned if there is no error */
children?: React.ReactNode;
/** Custom OUIA ID */
ouiaId?: string | number;
}

export interface ErrorPageState {
Expand Down Expand Up @@ -61,33 +63,36 @@ class ErrorBoundary extends React.Component<ErrorPageProps, ErrorPageState> {
}

render() {
const { ouiaId = 'ErrorBoundary', ...props } = this.props;

if (this.state.hasError) {
if (this.props.silent) {
return null;
}

return (
<React.Fragment>
<Title headingLevel="h1" size="2xl">{this.props.headerTitle}</Title>
<div data-ouia-component-id={ouiaId}>
<Title headingLevel="h1" size="2xl" ouiaId={`${ouiaId}-title`}>{props.headerTitle}</Title>
<ErrorState
errorTitle={this.props.errorTitle}
errorTitle={props.errorTitle}
errorDescription={
<>
<span>{this.props.errorDescription}</span>
<span>{props.errorDescription}</span>
{this.state.error && (
<ExpandableSection toggleText={this.props.errorToggleText ? this.props.errorToggleText : "Show details"}>
<ErrorStack error={this.state.error} />
<ExpandableSection toggleText={props.errorToggleText ? props.errorToggleText : "Show details"} data-ouia-component-id={`${ouiaId}-toggle`}>
<ErrorStack error={this.state.error} data-ouia-component-id={`${ouiaId}-stack`}/>
</ExpandableSection>
)}
</>
}
defaultErrorDescription={this.props.defaultErrorDescription}
defaultErrorDescription={props.defaultErrorDescription}
/>
</React.Fragment>
</div>
);
}

return this.props.children;
return props.children;
}
}
};

export default ErrorBoundary;
18 changes: 10 additions & 8 deletions packages/module/src/ErrorState/ErrorState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,29 @@ export interface ErrorStateProps extends Omit<EmptyStateProps, 'children'> {
defaultErrorDescription?: React.ReactNode;
/** Custom footer content */
customFooter?: React.ReactNode;
/** ErrorState OUIA ID */
ouiaId?: string | number;
}

const ErrorState: React.FunctionComponent<ErrorStateProps> = ({ errorTitle = 'Something went wrong', errorDescription, defaultErrorDescription, customFooter, ...props }: ErrorStateProps) => {
const ErrorState: React.FunctionComponent<ErrorStateProps> = ({ errorTitle = 'Something went wrong', errorDescription, defaultErrorDescription, customFooter, ouiaId = "ErrorState", ...props }: ErrorStateProps) => {
const classes = useStyles();
return (
<EmptyState variant={EmptyStateVariant.lg} {...props}>
<EmptyStateHeader titleText={<>{errorTitle}</>} icon={<EmptyStateIcon className={classes.errorIcon} icon={ExclamationCircleIcon} />} headingLevel="h4" />
<EmptyStateBody>
<EmptyStateHeader titleText={<>{errorTitle}</>} icon={<EmptyStateIcon className={classes.errorIcon} icon={ExclamationCircleIcon} data-ouia-component-id={`${ouiaId}-icon`} />} headingLevel="h4" data-ouia-component-id={`${ouiaId}-header`}/>
<EmptyStateBody data-ouia-component-id={`${ouiaId}-body`}>
<Stack>
{errorDescription ? <StackItem>{errorDescription}</StackItem> : defaultErrorDescription}
</Stack>
</EmptyStateBody>
<EmptyStateFooter>
<EmptyStateFooter data-ouia-component-id={`${ouiaId}-footer`}>
{ customFooter ||
(document.referrer ? (
<Button variant="primary" onClick={() => history.back()}>
Return to last page
<Button variant="primary" onClick={() => history.back()} ouiaId={`${ouiaId}-back-button`}>
Return to last page
</Button>
) : (
<Button variant="primary" component="a" href="." target="_blank" rel="noopener noreferrer">
Go to home page
<Button variant="primary" component="a" href="." target="_blank" rel="noopener noreferrer" ouiaId={`${ouiaId}-home-button`}>
Go to home page
</Button>
))}
</EmptyStateFooter>
Expand Down
35 changes: 19 additions & 16 deletions packages/module/src/InvalidObject/InvalidObject.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
import { Button, EmptyState, EmptyStateBody, EmptyStateFooter, EmptyStateHeader, EmptyStateVariant } from '@patternfly/react-core';
import { Button, EmptyState, EmptyStateBody, EmptyStateFooter, EmptyStateHeader, EmptyStateProps, EmptyStateVariant } from '@patternfly/react-core';

import NotFoundIcon from '../NotFoundIcon/NotFoundIcon';
import React from 'react';

export interface InvalidObjectProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> {
/** The URL that the landing page link points to */
toLandingPageUrl?: string;
/** The text label for the link that points back to the landing page */
toLandingPageText?: React.ReactNode;
export interface InvalidObjectProps extends Omit<EmptyStateProps, 'children' | 'title'> {
/** The URL that the home page link points to */
toHomePageUrl?: string;
/** The text label for the link that points back to the home page */
toHomePageText?: React.ReactNode;
/** The title for the invalid object message */
invalidObjectTitleText?: string;
/** The body text for the invalid object message */
invalidObjectBodyText?: string;
/** Custom OUIA ID */
ouiaId?: string | number;
}


const InvalidObject: React.FunctionComponent<InvalidObjectProps> = ({
toLandingPageUrl = window.location.origin,
toLandingPageText = 'Return to homepage',
toHomePageUrl = window.location.origin,
toHomePageText = 'Return to homepage',
invalidObjectTitleText = 'We lost that page',
invalidObjectBodyText = "Let's find you a new one. Try a new search or return home."
invalidObjectBodyText = "Let's find you a new one. Try a new search or return home.",
ouiaId = "InvalidObject",
...props
}: InvalidObjectProps) => (
<EmptyState variant={EmptyStateVariant.full}>
<EmptyStateHeader titleText={invalidObjectTitleText}icon={<NotFoundIcon />} headingLevel='h1' />
<EmptyStateBody>{invalidObjectBodyText}</EmptyStateBody>
<EmptyStateFooter>
<Button variant="link" component="a" href={toLandingPageUrl}>
{toLandingPageText}
<EmptyState variant={EmptyStateVariant.full} data-ouia-component-id={ouiaId} {...props}>
<EmptyStateHeader titleText={invalidObjectTitleText} icon={<NotFoundIcon data-ouia-component-id={`${ouiaId}-icon`} />} headingLevel='h1' data-ouia-component-id={`${ouiaId}-header`} />
<EmptyStateBody data-ouia-component-id={`${ouiaId}-body`}>{invalidObjectBodyText}</EmptyStateBody>
<EmptyStateFooter data-ouia-component-id={`${ouiaId}-footer`}>
<Button variant="link" component="a" href={toHomePageUrl} ouiaId={`${ouiaId}-home-button`}>
{toHomePageText}
</Button>
</EmptyStateFooter>
</EmptyState>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@ exports[`InvalidObject component should render 1`] = `
<div>
<div
class="pf-v5-c-empty-state"
data-ouia-component-id="InvalidObject"
>
<div
class="pf-v5-c-empty-state__content"
>
<div
class="pf-v5-c-empty-state__header"
data-ouia-component-id="InvalidObject-header"
>
<svg
class="icon404-0-2-1"
data-name="Layer 1"
data-ouia-component-id="InvalidObject-icon"
id="Icon404"
viewBox="0 0 131 131"
xmlns="http://www.w3.org/2000/svg"
Expand Down Expand Up @@ -264,16 +267,18 @@ exports[`InvalidObject component should render 1`] = `
</div>
<div
class="pf-v5-c-empty-state__body"
data-ouia-component-id="InvalidObject-body"
>
Let's find you a new one. Try a new search or return home.
</div>
<div
class="pf-v5-c-empty-state__footer"
data-ouia-component-id="InvalidObject-footer"
>
<a
aria-disabled="false"
class="pf-v5-c-button pf-m-link"
data-ouia-component-id="OUIA-Generated-Button-link-1"
data-ouia-component-id="InvalidObject-home-button"
data-ouia-component-type="PF5/Button"
data-ouia-safe="true"
href="http://localhost:5000"
Expand All @@ -288,16 +293,19 @@ exports[`InvalidObject component should render 1`] = `
"container": <div>
<div
class="pf-v5-c-empty-state"
data-ouia-component-id="InvalidObject"
>
<div
class="pf-v5-c-empty-state__content"
>
<div
class="pf-v5-c-empty-state__header"
data-ouia-component-id="InvalidObject-header"
>
<svg
class="icon404-0-2-1"
data-name="Layer 1"
data-ouia-component-id="InvalidObject-icon"
id="Icon404"
viewBox="0 0 131 131"
xmlns="http://www.w3.org/2000/svg"
Expand Down Expand Up @@ -545,16 +553,18 @@ exports[`InvalidObject component should render 1`] = `
</div>
<div
class="pf-v5-c-empty-state__body"
data-ouia-component-id="InvalidObject-body"
>
Let's find you a new one. Try a new search or return home.
</div>
<div
class="pf-v5-c-empty-state__footer"
data-ouia-component-id="InvalidObject-footer"
>
<a
aria-disabled="false"
class="pf-v5-c-button pf-m-link"
data-ouia-component-id="OUIA-Generated-Button-link-1"
data-ouia-component-id="InvalidObject-home-button"
data-ouia-component-type="PF5/Button"
data-ouia-safe="true"
href="http://localhost:5000"
Expand Down
Loading

0 comments on commit fec3374

Please sign in to comment.