Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ import ResourcesFullIcon from '@patternfly/react-icons/dist/esm/icons/resources-
import ExclamationTriangleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon';
import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';

export enum ProgressStepVariant {
default = 'default',
pending = 'pending',
success = 'success',
info = 'info',
danger = 'danger',
warning = 'warning'
}

export interface ProgressStepProps
extends React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement> {
/** Content rendered inside the progress step. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';
import { ProgressStep, ProgressStepVariant } from '../ProgressStep';
import { capitalize } from '../../../helpers';

jest.mock('@patternfly/react-icons/dist/esm/icons/check-circle-icon', () => () => 'Success icon mock');
jest.mock('@patternfly/react-icons/dist/esm/icons/resources-full-icon', () => () => 'Info icon mock');
jest.mock('@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon', () => () => 'Warning icon mock');
jest.mock('@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon', () => () => 'Danger icon mock');

test('Renders without children', () => {
render(
<div data-testid="progress-step">
<ProgressStep />
</div>
);

expect(screen.getByTestId('progress-step').firstChild).toBeVisible();
});

test('Renders children', () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByText('Test')).toBeVisible();
});

test('Renders with class pf-c-progress-stepper__step on the containing li element', () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByRole('listitem')).toHaveClass('pf-c-progress-stepper__step');
});

test('Renders with custom class name on the containing li element when className prop is provided', () => {
render(<ProgressStep className="custom-class">Test</ProgressStep>);
expect(screen.getByRole('listitem')).toHaveClass('custom-class');
});

['default', undefined].forEach(variant => {
test(`Renders with no additional classes when variant=${variant} on containing li element`, () => {
render(<ProgressStep variant={`${variant as ProgressStepVariant}`}>Test</ProgressStep>);
expect(screen.getByRole('listitem')).toHaveClass('pf-c-progress-stepper__step', { exact: true });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very cool! i haven't seen the exact argument before.

});
});

['success', 'info', 'warning', 'danger'].forEach(variant => {
test(`Does not render with class pf-m-${variant} by default on containing li element`, () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByRole('listitem')).not.toHaveClass(`pf-m-${variant}`);
});

test(`Renders with class pf-m-${variant} when variant = ${variant} on containing li element`, () => {
render(<ProgressStep variant={`${variant as ProgressStepVariant}`}>Test</ProgressStep>);
expect(screen.getByRole('listitem')).toHaveClass(`pf-m-${variant}`);
});

test(`Does not render with ${variant} variant icon by default`, () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.queryByText(`${capitalize(variant)} icon mock`)).not.toBeInTheDocument();
});

test(`Renders with ${variant} variant icon when variant = ${variant}`, () => {
render(<ProgressStep variant={`${variant as ProgressStepVariant}`}>Test</ProgressStep>);
expect(screen.getByText(`${capitalize(variant)} icon mock`)).toBeVisible();
});
});

test('Does not render with class pf-m-pending by default on containing li element', () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByRole('listitem')).not.toHaveClass('pf-m-pending');
});

test('Renders with class pf-m-pending when variant = pending on containing li element', () => {
render(<ProgressStep variant="pending">Test</ProgressStep>);
expect(screen.getByRole('listitem')).toHaveClass('pf-m-pending');
});

test('Renders the element passed via the icon prop', () => {
render(<ProgressStep icon="Custom Icon">Test</ProgressStep>);
expect(screen.getByText('Custom Icon')).toBeVisible();
});

test('Renders the icon element inside span element with class pf-c-progress-stepper__step-icon', () => {
render(<ProgressStep icon="Custom Icon">Test</ProgressStep>);
expect(screen.getByText('Custom Icon')).toHaveClass('pf-c-progress-stepper__step-icon');
});

test('Does not render with class pf-m-current by default on containing li element', () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByRole('listitem')).not.toHaveClass('pf-m-current');
});

test('Renders with class pf-m-current on containing li element when isCurrent is passed', () => {
render(<ProgressStep isCurrent>Test</ProgressStep>);
expect(screen.getByRole('listitem')).toHaveClass('pf-m-current');
});

test('Renders without aria-current on containing li element by default', () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByRole('listitem')).not.toHaveAttribute('aria-current');
});

test(`Renders with a aria-current of "step" on containing li element when isCurrent is passed`, () => {
render(<ProgressStep isCurrent>Test</ProgressStep>);
expect(screen.getByRole('listitem')).toHaveAttribute('aria-current', 'step');
});

test(`Renders with the aria label on containing li element passed via prop`, () => {
render(<ProgressStep aria-label="Test label">Test</ProgressStep>);
expect(screen.getByRole('listitem')).toHaveAccessibleName('Test label');
});

test('Renders the element passed via the description prop', () => {
render(<ProgressStep description={<button>Description</button>}>Test</ProgressStep>);
expect(screen.getByRole('button', { name: 'Description' })).toBeVisible();
});

test('Renders the description element inside div element with class pf-c-progress-stepper__step-description', () => {
render(<ProgressStep description="Description">Test</ProgressStep>);
expect(screen.getByText('Description')).toHaveClass('pf-c-progress-stepper__step-description');
});

test('Renders children inside class pf-c-progress-stepper__step-title', () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByText('Test')).toHaveClass('pf-c-progress-stepper__step-title');
});

test('Renders Component element as div by default', () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByText('Test')).toHaveProperty('nodeName', 'DIV');
});

test('Renders Component element as button when popoverRender is defined', () => {
render(<ProgressStep popoverRender={() => <div>Popover</div>}>Test</ProgressStep>);
expect(screen.getByRole('button')).toBeVisible();
});

test('Does not render with class pf-m-help-text by default on Component element', () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByText('Test')).not.toHaveClass('pf-m-help-text');
});

test('Renders with class pf-m-help-text when popoverRender is defined', () => {
render(<ProgressStep popoverRender={() => <div>Popover</div>}>Test</ProgressStep>);
expect(screen.getByText('Test')).toHaveClass('pf-m-help-text');
});

test('Does not renders with aria-labelledBy by default on Component element', () => {
render(<ProgressStep>Test</ProgressStep>);
expect(screen.getByText('Test')).not.toHaveAccessibleName();
});

test('Renders with an accessible name that matches children', () => {
render(
<ProgressStep id="test-id" titleId="title-id">
Test
</ProgressStep>
);
expect(screen.getByText('Test')).toHaveAccessibleName('Test');
});

test('Renders with popoverRender element', () => {
render(<ProgressStep popoverRender={() => <div>Popover</div>}>Test</ProgressStep>);
expect(screen.getByText('Popover')).toBeVisible();
});

test('Renders with inherited element props spread to the component', () => {
render(
<>
<ProgressStep aria-describedby="labelling-id" aria-label="Test label" />
<p id="labelling-id">Described by text</p>
</>
);

expect(screen.getByLabelText('Test label')).toHaveAccessibleDescription('Described by text');
});

test('Matches snapshot', () => {
const { asFragment } = render(<ProgressStep>Test</ProgressStep>);
expect(asFragment()).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -1,143 +1,57 @@
import * as React from 'react';
import { render, screen } from '@testing-library/react';
import { ProgressStepper } from '../ProgressStepper';
import { ProgressStep } from '../ProgressStep';
import InProgressIcon from '@patternfly/react-icons/dist/esm/icons/in-progress-icon';

describe('ProgressStepper', () => {
test('renders content', () => {
const { asFragment } = render(
<ProgressStepper>
<ProgressStep>First</ProgressStep>
<ProgressStep>Second</ProgressStep>
<ProgressStep>Third</ProgressStep>
</ProgressStepper>
);
expect(asFragment()).toMatchSnapshot();
});

test('gets custom class and id', () => {
const { asFragment } = render(
<ProgressStepper className="custom-class" id="test-id">
<ProgressStep>First</ProgressStep>
<ProgressStep>Second</ProgressStep>
<ProgressStep>Third</ProgressStep>
</ProgressStepper>
);
expect(asFragment()).toMatchSnapshot();
});

test('renders vertically', () => {
const { asFragment } = render(
<ProgressStepper isVertical>
<ProgressStep>First</ProgressStep>
<ProgressStep>Second</ProgressStep>
<ProgressStep>Third</ProgressStep>
</ProgressStepper>
);
expect(asFragment()).toMatchSnapshot();
});

test('renders compact', () => {
const { asFragment } = render(
<ProgressStepper isCompact>
<ProgressStep>First</ProgressStep>
<ProgressStep>Second</ProgressStep>
<ProgressStep>Third</ProgressStep>
</ProgressStepper>
);
expect(asFragment()).toMatchSnapshot();
});

test('renders center aligned', () => {
const { asFragment } = render(
<ProgressStepper isCenterAligned>
<ProgressStep>First</ProgressStep>
<ProgressStep>Second</ProgressStep>
<ProgressStep>Third</ProgressStep>
</ProgressStepper>
);
expect(asFragment()).toMatchSnapshot();
});
test('Renders without children', () => {
render(
<div data-testid="progress-stepper">
<ProgressStepper />
</div>
);
expect(screen.getByTestId('progress-stepper').firstChild).toBeVisible();
});

describe('ProgressStep', () => {
test('renders content', () => {
const { asFragment } = render(<ProgressStep>Title</ProgressStep>);
expect(asFragment()).toMatchSnapshot();
});

Object.values(['default', 'success', 'info', 'pending', 'warning', 'danger']).forEach(variant => {
test(`renders ${variant} variant`, () => {
const { asFragment } = render(
<ProgressStep
variant={variant as 'default' | 'success' | 'info' | 'pending' | 'warning' | 'danger'}
aria-label={variant}
>
{variant} step
</ProgressStep>
);
expect(asFragment()).toMatchSnapshot();
});
});

test('renders current', () => {
const { asFragment } = render(<ProgressStep isCurrent>Title</ProgressStep>);
expect(asFragment()).toMatchSnapshot();
});
test('Renders children', () => {
render(<ProgressStepper>Test</ProgressStepper>);
expect(screen.getByRole('list')).toBeVisible();
});

test('renders help text styling', () => {
const { asFragment } = render(<ProgressStep popoverRender={() => <div></div>}>Title</ProgressStep>);
expect(asFragment()).toMatchSnapshot();
});
test('Renders with only class name pf-c-progress-stepper by default', () => {
render(<ProgressStepper>Test</ProgressStepper>);
expect(screen.getByRole('list')).toHaveClass('pf-c-progress-stepper', { exact: true });
});

test('renders custom icon', () => {
const { asFragment } = render(<ProgressStep icon={<InProgressIcon />}>Title</ProgressStep>);
expect(asFragment()).toMatchSnapshot();
});
test('Renders with class name pf-c-progress-stepper', () => {
render(<ProgressStepper>Test</ProgressStepper>);
expect(screen.getByRole('list')).toHaveClass('pf-c-progress-stepper');
});

test('renders custom null icon - removing default from variant', () => {
const { asFragment } = render(
<ProgressStep icon={null} variant="success">
Title
</ProgressStep>
);
expect(asFragment()).toMatchSnapshot();
});
test('Renders with custom class name when className prop is provided', () => {
render(<ProgressStepper className="custom-class">Test</ProgressStepper>);
expect(screen.getByRole('list')).toHaveClass('custom-class');
});

test('renders description', () => {
const { asFragment } = render(<ProgressStep description="This is a description">Title</ProgressStep>);
expect(asFragment()).toMatchSnapshot();
});
test('Renders with class name pf-m-center when isCenterAligned prop is passed', () => {
render(<ProgressStepper isCenterAligned>Test</ProgressStepper>);
expect(screen.getByRole('list')).toHaveClass('pf-m-center');
});

test('renders description class and text', () => {
render(
<ProgressStep
description="Test description"
>
Title
</ProgressStep>
);
test('Renders with class name pf-m-vertical when isVertical prop is passed', () => {
render(<ProgressStepper isVertical>Test</ProgressStepper>);
expect(screen.getByRole('list')).toHaveClass('pf-m-vertical');
});

expect(screen.getByText('Test description')).toBeVisible();
expect(screen.getByText('Test description')).toHaveClass('pf-c-progress-stepper__step-description');
test('Renders with class name pf-m-compact when isCompact prop is passed', () => {
render(<ProgressStepper isCompact>Test</ProgressStepper>);
expect(screen.getByRole('list')).toHaveClass('pf-m-compact');
});

test('renders description line break', () => {
render(
<ProgressStep
description={
<>
Testing description
<br />
Line break
</>
}
>
Title
</ProgressStep>
);
test('Renders with inherited element props spread to the component', () => {
render(<ProgressStepper aria-label="Test label">Test</ProgressStepper>);
expect(screen.getByRole('list')).toHaveAccessibleName('Test label');
});

expect(screen.getByText("Testing descriptionLine break")).toBeVisible();
test('Matches the snapshot', () => {
const { asFragment } = render(<ProgressStepper>Test</ProgressStepper>);
expect(asFragment()).toMatchSnapshot();
});
Loading