diff --git a/packages/react/package.json b/packages/react/package.json index 83886549a026..5f4c480d2954 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -94,6 +94,7 @@ "babel-preset-carbon": "^0.3.0", "browserify-zlib": "^0.2.0", "browserslist-config-carbon": "^11.0.0", + "clipboardy": "^2.1.0", "css-loader": "^6.5.1", "enquirer": "^2.3.6", "fast-glob": "^3.2.7", diff --git a/packages/react/src/components/ProgressIndicator/ProgressIndicator-story.js b/packages/react/src/components/ProgressIndicator/ProgressIndicator-story.js deleted file mode 100644 index 9b739b9769d4..000000000000 --- a/packages/react/src/components/ProgressIndicator/ProgressIndicator-story.js +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2018 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -import React from 'react'; -import { withKnobs, number, boolean, text } from '@storybook/addon-knobs'; -import { action } from '@storybook/addon-actions'; -import { ProgressIndicator, ProgressStep } from '../ProgressIndicator'; -import ProgressIndicatorSkeleton from '../ProgressIndicator/ProgressIndicator.Skeleton'; -import mdx from './ProgressIndicator.mdx'; - -export default { - title: 'Components/ProgressIndicator', - component: ProgressIndicator, - decorators: [withKnobs], - parameters: { - docs: { - page: mdx, - }, - }, - subcomponents: { - ProgressStep, - }, -}; - -export const Default = () => ( - - - - - - - -); - -export const Interactive = () => ( - - - - - -); - -Interactive.storyName = 'interactive'; - -export const Skeleton = () => ; - -Skeleton.storyName = 'skeleton'; diff --git a/packages/react/src/components/ProgressIndicator/ProgressIndicator-test.js b/packages/react/src/components/ProgressIndicator/ProgressIndicator-test.js deleted file mode 100644 index 235452e7b01b..000000000000 --- a/packages/react/src/components/ProgressIndicator/ProgressIndicator-test.js +++ /dev/null @@ -1,185 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2018 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -import React from 'react'; -import { ProgressIndicator, ProgressStep } from '../ProgressIndicator'; -import ProgressIndicatorSkeleton from '../ProgressIndicator/ProgressIndicator.Skeleton'; -import { shallow, mount } from 'enzyme'; - -const prefix = 'cds'; - -describe('ProgressIndicator', () => { - describe('Renders as expected', () => { - const progress = ( - - - - - - - - - ); - const list = shallow(progress); - const mountedList = mount(progress); - - beforeEach(() => { - mountedList.setProps({ currentIndex: 3 }); - }); - - it('should be a ul element', () => { - expect(list.find('ul').length).toEqual(1); - }); - - it('should render children as expected', () => { - expect(list.find(ProgressStep).length).toEqual(6); - }); - - it('should have the initial currentIndex from props', () => { - expect(list.state().currentIndex).toEqual(3); - }); - - it('should update state when currentIndex is changed', () => { - list.setProps({ currentIndex: 1 }); - expect(list.state().currentIndex).toEqual(1); - list.setProps({ currentIndex: 0 }); - expect(list.state().currentIndex).toEqual(0); - }); - - it('should avoid updating state unless actual change in currentIndex is detected', () => { - list.setProps({ currentIndex: 1 }); - list.setState({ currentIndex: 2 }); - list.setProps({ currentIndex: 1 }); - expect(list.state().currentIndex).toEqual(2); - }); - - it('should trigger onChange if clicked', () => { - const mockOnChange = jest.fn(); - - mountedList.setProps({ onChange: mockOnChange }); - mountedList.find(ProgressStep).at(0).find('button').simulate('click'); - expect(mockOnChange).toHaveBeenCalledWith(0); - }); - - describe('ProgressStep', () => { - it('should render with correct base className', () => { - expect( - mountedList - .find(ProgressStep) - .at(0) - .children() - .hasClass(`${prefix}--progress-step`) - ).toEqual(true); - }); - - it('should render with a label', () => { - expect(mountedList.find(ProgressStep).at(0).prop('label')).toEqual( - 'label' - ); - }); - - it('should render with a description', () => { - expect( - mountedList.find(ProgressStep).at(0).prop('description') - ).toEqual('Step 1: Getting Started with Node.js'); - }); - - it('should render description in node', () => { - expect(mountedList.find('ProgressStep title').at(0).text()).toEqual( - 'Step 1: Getting Started with Node.js' - ); - }); - - describe('current', () => { - it('should render a current ProgressStep with correct className', () => { - expect( - mountedList - .find(ProgressStep) - .at(3) - .children() - .hasClass(`${prefix}--progress-step--current`) - ).toEqual(true); - }); - - it('should render a current ProgressStep with correct props', () => { - expect(mountedList.find(ProgressStep).at(3).prop('current')).toBe( - true - ); - }); - }); - - describe('complete', () => { - it('should render any completed ProgressSteps with correct className', () => { - expect( - mountedList - .find(ProgressStep) - .at(0) - .children() - .hasClass(`${prefix}--progress-step--complete`) - ).toEqual(true); - }); - it('should render any completed ProgressSteps with correct props', () => { - expect(list.find(ProgressStep).at(0).prop('complete')).toBe(true); - }); - }); - - describe('incomplete', () => { - it('should render any incomplete ProgressSteps with correct className', () => { - expect( - mountedList - .find(ProgressStep) - .at(5) - .children() - .hasClass(`${prefix}--progress-step--incomplete`) - ).toEqual(true); - }); - it('should render any incomplete ProgressSteps with correct props', () => { - expect(list.find(ProgressStep).at(5).prop('complete')).toBe(false); - }); - - it('should render any clickable ProgressSteps with correct classname', () => { - mountedList.setProps({ onChange: jest.fn() }); - expect( - mountedList.find(`.${prefix}--progress-step-button`) - ).toHaveLength(6); // one button for each div - expect( - mountedList.find(`.${prefix}--progress-step-button--unclickable`) - ).toHaveLength(1); // only the current step should be unclickable - }); - }); - }); - }); -}); - -describe('ProgressIndicatorSkeleton', () => { - describe('Renders as expected', () => { - const wrapper = shallow(<ProgressIndicatorSkeleton />); - - it('Has the expected classes', () => { - expect(wrapper.hasClass(`${prefix}--skeleton`)).toEqual(true); - expect(wrapper.hasClass(`${prefix}--progress`)).toEqual(true); - }); - }); -}); diff --git a/packages/react/src/components/ProgressIndicator/ProgressIndicator.js b/packages/react/src/components/ProgressIndicator/ProgressIndicator.js index 64ec6bc98481..81a772f8eb53 100644 --- a/packages/react/src/components/ProgressIndicator/ProgressIndicator.js +++ b/packages/react/src/components/ProgressIndicator/ProgressIndicator.js @@ -5,17 +5,17 @@ * LICENSE file in the root directory of this source tree. */ +import cx from 'classnames'; import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import classnames from 'classnames'; +import React, { useState } from 'react'; +import { keys, matches } from '../../internal/keyboard'; import { CheckmarkOutline, Warning, CircleDash, Incomplete, } from '@carbon/icons-react'; -import { keys, matches } from '../../internal/keyboard'; -import { usePrefix, PrefixContext } from '../../internal/usePrefix'; +import { usePrefix } from '../../internal/usePrefix'; const defaultTranslations = { 'carbon.progress-step.complete': 'Complete', @@ -27,8 +27,97 @@ const defaultTranslations = { function translateWithId(messageId) { return defaultTranslations[messageId]; } +function ProgressIndicator({ + children, + className: customClassName, + currentIndex: controlledIndex = 0, + onChange, + spaceEqually, + vertical, + ...rest +}) { + const prefix = usePrefix(); + const [currentIndex, setCurrentIndex] = useState(controlledIndex); + const [prevControlledIndex, setPrevControlledIndex] = + useState(controlledIndex); + const className = cx({ + [`${prefix}--progress`]: true, + [`${prefix}--progress--vertical`]: vertical, + [`${prefix}--progress--space-equal`]: spaceEqually && !vertical, + [customClassName]: customClassName, + }); + + if (controlledIndex !== prevControlledIndex) { + setCurrentIndex(controlledIndex); + setPrevControlledIndex(controlledIndex); + } + + return ( + <ul className={className} {...rest}> + {React.Children.map(children, (child, index) => { + // only setup click handlers if onChange event is passed + const onClick = onChange ? () => onChange(index) : undefined; + if (index === currentIndex) { + return React.cloneElement(child, { + complete: child.props.complete, + current: child.props.complete ? false : true, + index, + onClick, + }); + } + if (index < currentIndex) { + return React.cloneElement(child, { + complete: true, + index, + onClick, + }); + } + if (index > currentIndex) { + return React.cloneElement(child, { + complete: child.props.complete || false, + index, + onClick, + }); + } + return null; + })} + </ul> + ); +} + +ProgressIndicator.propTypes = { + /** + * Provide `<ProgressStep>` components to be rendered in the + * `<ProgressIndicator>` + */ + children: PropTypes.node, + + /** + * Provide an optional className to be applied to the containing node + */ + className: PropTypes.string, + + /** + * Optionally specify the current step array index + */ + currentIndex: PropTypes.number, -export function ProgressStep({ + /** + * Optional callback called if a ProgressStep is clicked on. Returns the index of the step. + */ + onChange: PropTypes.func, + + /** + * Specify whether the progress steps should be split equally in size in the div + */ + spaceEqually: PropTypes.bool, + /** + * Determines whether or not the ProgressIndicator should be rendered vertically. + */ + vertical: PropTypes.bool, +}; + +function ProgressStep({ label, description, className, @@ -42,7 +131,7 @@ export function ProgressStep({ ...rest }) { const prefix = usePrefix(); - const classes = classnames({ + const classes = cx({ [`${prefix}--progress-step`]: true, [`${prefix}--progress-step--current`]: current, [`${prefix}--progress-step--complete`]: complete, @@ -105,7 +194,7 @@ export function ProgressStep({ <li className={classes}> <button type="button" - className={classnames(`${prefix}--progress-step-button`, { + className={cx(`${prefix}--progress-step-button`, { [`${prefix}--progress-step-button--unclickable`]: !onClick || current, })} disabled={disabled} @@ -207,107 +296,4 @@ ProgressStep.defaultProps = { translateWithId, }; -export class ProgressIndicator extends Component { - state = {}; - - static propTypes = { - /** - * Provide `<ProgressStep>` components to be rendered in the - * `<ProgressIndicator>` - */ - children: PropTypes.node, - - /** - * Provide an optional className to be applied to the containing node - */ - className: PropTypes.string, - - /** - * Optionally specify the current step array index - */ - currentIndex: PropTypes.number, - - /** - * Optional callback called if a ProgressStep is clicked on. Returns the index of the step. - */ - onChange: PropTypes.func, - - /** - * Specify whether the progress steps should be split equally in size in the div - */ - spaceEqually: PropTypes.bool, - /** - * Determines whether or not the ProgressIndicator should be rendered vertically. - */ - vertical: PropTypes.bool, - }; - - static contextType = PrefixContext; - - static defaultProps = { - currentIndex: 0, - }; - - static getDerivedStateFromProps({ currentIndex }, state) { - const { prevCurrentIndex } = state; - return prevCurrentIndex === currentIndex - ? null - : { - currentIndex, - prevCurrentIndex: currentIndex, - }; - } - - renderSteps = () => { - const { onChange } = this.props; - - return React.Children.map(this.props.children, (child, index) => { - // only setup click handlers if onChange event is passed - const onClick = onChange ? () => onChange(index) : undefined; - if (index === this.state.currentIndex) { - return React.cloneElement(child, { - current: true, - index, - onClick, - }); - } - if (index < this.state.currentIndex) { - return React.cloneElement(child, { - complete: true, - index, - onClick, - }); - } - if (index > this.state.currentIndex) { - return React.cloneElement(child, { - complete: child.props.complete || false, - index, - onClick, - }); - } - return null; - }); - }; - - render() { - const { - className, - currentIndex, // eslint-disable-line no-unused-vars - vertical, - spaceEqually, - ...other - } = this.props; - const prefix = this.context; - const classes = classnames({ - [`${prefix}--progress`]: true, - [`${prefix}--progress--vertical`]: vertical, - [`${prefix}--progress--space-equal`]: spaceEqually && !vertical, - [className]: className, - }); - return ( - <ul className={classes} {...other}> - {this.renderSteps()} - </ul> - ); - } -} +export { ProgressIndicator, ProgressStep }; diff --git a/packages/react/src/components/ProgressIndicator/next/ProgressIndicator.stories.js b/packages/react/src/components/ProgressIndicator/ProgressIndicator.stories.js similarity index 93% rename from packages/react/src/components/ProgressIndicator/next/ProgressIndicator.stories.js rename to packages/react/src/components/ProgressIndicator/ProgressIndicator.stories.js index b12d409dc4d1..97b8a2b522a6 100644 --- a/packages/react/src/components/ProgressIndicator/next/ProgressIndicator.stories.js +++ b/packages/react/src/components/ProgressIndicator/ProgressIndicator.stories.js @@ -6,12 +6,8 @@ */ import React from 'react'; -import { - ProgressIndicator, - ProgressStep, - ProgressIndicatorSkeleton, -} from '../'; -import mdx from '../ProgressIndicator.mdx'; +import { ProgressIndicator, ProgressStep, ProgressIndicatorSkeleton } from './'; +import mdx from './ProgressIndicator.mdx'; export default { title: 'Components/ProgressIndicator', diff --git a/packages/react/src/components/ProgressIndicator/__tests__/ProgressIndicator-test.js b/packages/react/src/components/ProgressIndicator/__tests__/ProgressIndicator-test.js new file mode 100644 index 000000000000..ab47d2411ec6 --- /dev/null +++ b/packages/react/src/components/ProgressIndicator/__tests__/ProgressIndicator-test.js @@ -0,0 +1,279 @@ +/** + * Copyright IBM Corp. 2022 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React from 'react'; +import { ProgressIndicator, ProgressStep } from '../ProgressIndicator'; +import userEvent from '@testing-library/user-event'; +import { render, screen } from '@testing-library/react'; + +describe('ProgressIndicator', () => { + describe('renders as expected - Component API', () => { + it('should spread extra props onto outermost element', () => { + const { container } = render( + <ProgressIndicator data-testid="test-id"> + <ProgressStep + complete + label="First step" + description="Step 1: Getting started with Carbon Design System" + secondaryLabel="Optional label" + /> + <ProgressStep + current + label="Second step with tooltip" + description="Step 2: Getting started with Carbon Design System" + /> + </ProgressIndicator> + ); + + expect(container.firstChild).toHaveAttribute('data-testid', 'test-id'); + }); + + it('should support a custom `className` prop on the outermost element', () => { + const { container } = render( + <ProgressIndicator className="custom-class"> + <ProgressStep + complete + label="First step" + description="Step 1: Getting started with Carbon Design System" + secondaryLabel="Optional label" + /> + <ProgressStep + current + label="Second step with tooltip" + description="Step 2: Getting started with Carbon Design System" + /> + </ProgressIndicator> + ); + + expect(container.firstChild).toHaveClass('custom-class'); + }); + + it('should respect currentIndex prop', () => { + render( + <ProgressIndicator currentIndex={0}> + <ProgressStep + label="First step" + description="Step 1: Getting started with Carbon Design System" + secondaryLabel="Optional label" + /> + <ProgressStep + label="Second step with tooltip" + description="Step 2: Getting started with Carbon Design System" + /> + </ProgressIndicator> + ); + + expect(screen.getAllByRole('listitem')[0]).toHaveClass( + 'cds--progress-step--current' + ); + }); + + it('should call onChange when expected', () => { + const onChange = jest.fn(); + render( + <ProgressIndicator onChange={onChange} currentIndex={1}> + <ProgressStep + complete + label="First step" + description="Step 1: Getting started with Carbon Design System" + secondaryLabel="Optional label" + /> + <ProgressStep + current + label="Second step with tooltip" + description="Step 2: Getting started with Carbon Design System" + /> + </ProgressIndicator> + ); + + userEvent.click(screen.getByTitle('First step')); + + expect(onChange).toHaveBeenCalled(); + }); + + it('should respect spaceEqually prop', () => { + render( + <ProgressIndicator spaceEqually> + <ProgressStep + complete + label="First step" + description="Step 1: Getting started with Carbon Design System" + secondaryLabel="Optional label" + /> + <ProgressStep + current + label="Second step with tooltip" + description="Step 2: Getting started with Carbon Design System" + /> + </ProgressIndicator> + ); + + expect(screen.getByRole('list')).toHaveClass( + 'cds--progress--space-equal' + ); + }); + + it('should respect vertical prop', () => { + render( + <ProgressIndicator vertical> + <ProgressStep + complete + label="First step" + description="Step 1: Getting started with Carbon Design System" + secondaryLabel="Optional label" + /> + <ProgressStep + current + label="Second step with tooltip" + description="Step 2: Getting started with Carbon Design System" + /> + </ProgressIndicator> + ); + + expect(screen.getByRole('list')).toHaveClass('cds--progress--vertical'); + }); + }); +}); + +describe('ProgressStep', () => { + describe('renders as expected - Component API', () => { + it('should spread extra props onto outermost element', () => { + const { container } = render( + <ProgressStep label="First step" data-testid="test-id" /> + ); + + expect(container.firstChild.firstChild).toHaveAttribute( + 'data-testid', + 'test-id' + ); + }); + + it('should support a custom `className` prop on the outermost element', () => { + const { container } = render( + <ProgressStep label="First step" className="custom-class" /> + ); + + expect(container.firstChild).toHaveClass('custom-class'); + }); + + it('should respect complete prop', () => { + render(<ProgressStep label="First step" complete />); + + expect(screen.getByText('Complete')).toBeInTheDocument(); + expect(screen.getByRole('listitem')).toHaveClass( + 'cds--progress-step--complete' + ); + }); + + it('should respect current prop', () => { + render(<ProgressStep label="First step" current />); + + expect(screen.getByText('Current')).toBeInTheDocument(); + expect(screen.getByRole('listitem')).toHaveClass( + 'cds--progress-step--current' + ); + }); + + it('should respect description prop', () => { + render(<ProgressStep label="First step" description="Step 1" />); + + expect(screen.getByText('First step')).toBeInTheDocument(); + }); + + it('should respect disabled prop', () => { + render(<ProgressStep label="First step" disabled />); + + expect(screen.getByRole('listitem')).toHaveClass( + 'cds--progress-step--disabled' + ); + expect(screen.getByRole('button')).toHaveAttribute('disabled'); + expect(screen.getByRole('button')).toHaveClass( + 'cds--progress-step-button--unclickable' + ); + }); + + it('should respect index prop', () => { + render(<ProgressStep label="First step" index={3} />); + + expect(screen.getByRole('button')).toHaveAttribute('index', '3'); + }); + + it('should respect invalid prop', () => { + render(<ProgressStep label="First step" invalid />); + + expect(screen.getByText('Invalid')).toBeDefined(); + }); + + it('should respect label prop', () => { + render(<ProgressStep label="First step" />); + + expect(screen.getByRole('button')).toHaveAttribute('title', 'First step'); + }); + + it('should call onClick when expected', () => { + const onClick = jest.fn(); + render(<ProgressStep label="First step" onClick={onClick} />); + + userEvent.click(screen.getByRole('button')); + expect(onClick).toHaveBeenCalled(); + }); + + it('should respect secondaryLabel prop', () => { + render( + <ProgressStep label="First step" secondaryLabel="Prompt for step" /> + ); + + expect(screen.getByText('Prompt for step')).toBeInTheDocument(); + }); + + it('should respect translateWithId prop', () => { + const translations = { + 'carbon.progress-step.complete': 'Terminé', + 'carbon.progress-step.incomplete': 'Partiel', + 'carbon.progress-step.current': 'Actuel', + 'carbon.progress-step.invalid': 'Non valide', + }; + + render( + <ProgressIndicator> + <ProgressStep + label="First step" + complete + translateWithId={(messageId) => { + return translations[messageId]; + }} + /> + <ProgressStep + label="First step" + invalid + translateWithId={(messageId) => { + return translations[messageId]; + }} + /> + <ProgressStep + label="First step" + current + translateWithId={(messageId) => { + return translations[messageId]; + }} + /> + <ProgressStep + label="First step" + translateWithId={(messageId) => { + return translations[messageId]; + }} + /> + </ProgressIndicator> + ); + + expect(screen.getByText('Terminé')).toBeInTheDocument(); + expect(screen.getByText('Actuel')).toBeInTheDocument(); + expect(screen.getByText('Non valide')).toBeInTheDocument(); + expect(screen.getByText('Partiel')).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/react/src/components/ProgressIndicator/index.js b/packages/react/src/components/ProgressIndicator/index.js index 68b46bee774e..52b92fd26258 100644 --- a/packages/react/src/components/ProgressIndicator/index.js +++ b/packages/react/src/components/ProgressIndicator/index.js @@ -5,16 +5,5 @@ * LICENSE file in the root directory of this source tree. */ -import * as FeatureFlags from '@carbon/feature-flags'; -import { default as ProgressIndicatorSkeleton } from './ProgressIndicator.Skeleton'; -import { - ProgressIndicator as ProgressIndicatorClassic, - ProgressStep, -} from './ProgressIndicator'; -import { ProgressIndicator as ProgressIndicatorNext } from './next/ProgressIndicator'; - -const ProgressIndicator = FeatureFlags.enabled('enable-v11-release') - ? ProgressIndicatorNext - : ProgressIndicatorClassic; - -export { ProgressIndicator, ProgressIndicatorSkeleton, ProgressStep }; +export { default as ProgressIndicatorSkeleton } from './ProgressIndicator.Skeleton'; +export * from './ProgressIndicator'; diff --git a/packages/react/src/components/ProgressIndicator/next/ProgressIndicator.js b/packages/react/src/components/ProgressIndicator/next/ProgressIndicator.js deleted file mode 100644 index d977d1adb5fa..000000000000 --- a/packages/react/src/components/ProgressIndicator/next/ProgressIndicator.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2018 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -import cx from 'classnames'; -import PropTypes from 'prop-types'; -import React, { useState } from 'react'; -import { usePrefix } from '../../../internal/usePrefix'; - -function ProgressIndicator({ - children, - className: customClassName, - currentIndex: controlledIndex = 0, - onChange, - spaceEqually, - vertical, - ...rest -}) { - const prefix = usePrefix(); - const [currentIndex, setCurrentIndex] = useState(controlledIndex); - const [prevControlledIndex, setPrevControlledIndex] = - useState(controlledIndex); - const className = cx({ - [`${prefix}--progress`]: true, - [`${prefix}--progress--vertical`]: vertical, - [`${prefix}--progress--space-equal`]: spaceEqually && !vertical, - [customClassName]: customClassName, - }); - - if (controlledIndex !== prevControlledIndex) { - setCurrentIndex(controlledIndex); - setPrevControlledIndex(controlledIndex); - } - - return ( - <ul className={className} {...rest}> - {React.Children.map(children, (child, index) => { - // only setup click handlers if onChange event is passed - const onClick = onChange ? () => onChange(index) : undefined; - if (index === currentIndex) { - return React.cloneElement(child, { - complete: child.props.complete, - current: child.props.complete ? false : true, - index, - onClick, - }); - } - if (index < currentIndex) { - return React.cloneElement(child, { - complete: true, - index, - onClick, - }); - } - if (index > currentIndex) { - return React.cloneElement(child, { - complete: child.props.complete || false, - index, - onClick, - }); - } - return null; - })} - </ul> - ); -} - -ProgressIndicator.propTypes = { - /** - * Provide `<ProgressStep>` components to be rendered in the - * `<ProgressIndicator>` - */ - children: PropTypes.node, - - /** - * Provide an optional className to be applied to the containing node - */ - className: PropTypes.string, - - /** - * Optionally specify the current step array index - */ - currentIndex: PropTypes.number, - - /** - * Optional callback called if a ProgressStep is clicked on. Returns the index of the step. - */ - onChange: PropTypes.func, - - /** - * Specify whether the progress steps should be split equally in size in the div - */ - spaceEqually: PropTypes.bool, - /** - * Determines whether or not the ProgressIndicator should be rendered vertically. - */ - vertical: PropTypes.bool, -}; - -export { ProgressIndicator }; diff --git a/packages/react/src/components/ProgressIndicator/next/__tests__/ProgressIndicator-test.js b/packages/react/src/components/ProgressIndicator/next/__tests__/ProgressIndicator-test.js deleted file mode 100644 index 578afcb1f6d0..000000000000 --- a/packages/react/src/components/ProgressIndicator/next/__tests__/ProgressIndicator-test.js +++ /dev/null @@ -1,166 +0,0 @@ -/** - * Copyright IBM Corp. 2016, 2018 - * - * This source code is licensed under the Apache-2.0 license found in the - * LICENSE file in the root directory of this source tree. - */ - -import { mount } from 'enzyme'; -import React from 'react'; -import { ProgressIndicator } from '../ProgressIndicator'; -import { ProgressStep } from '../../'; - -const prefix = 'cds'; - -function getActiveIndex(wrapper) { - return wrapper - .find(`.${prefix}--progress-step--current`) - .parent() - .prop('index'); -} - -describe('ProgressIndicator', () => { - describe('Renders as expected', () => { - let list; - - beforeEach(() => { - list = mount( - <ProgressIndicator className="some-class" currentIndex={3}> - <ProgressStep - label="label" - description="Step 1: Getting Started with Node.js" - /> - <ProgressStep - label="label" - description="Step 2: Getting Started with Node.js" - /> - <ProgressStep - label="label" - description="Step 3: Getting Started with Node.js" - /> - <ProgressStep - label="label" - description="Step 4: Getting Started with Node.js" - /> - <ProgressStep - label="label" - description="Step 5: Getting Started with Node.js" - /> - <ProgressStep - label="label" - description="Step 6: Getting Started with Node.js" - /> - </ProgressIndicator> - ); - }); - - it('should be a ul element', () => { - expect(list.find('ul').length).toEqual(1); - }); - - it('should render children as expected', () => { - expect(list.find(ProgressStep).length).toEqual(6); - }); - - it('should have the initial currentIndex from props', () => { - expect(getActiveIndex(list)).toEqual(3); - }); - - it('should update state when currentIndex is changed', () => { - list.setProps({ currentIndex: 1 }); - expect(getActiveIndex(list)).toEqual(1); - list.setProps({ currentIndex: 0 }); - expect(getActiveIndex(list)).toEqual(0); - }); - - it('should trigger onChange if clicked', () => { - const mockOnChange = jest.fn(); - - list.setProps({ onChange: mockOnChange }); - list.find(ProgressStep).at(0).find('button').simulate('click'); - expect(mockOnChange).toHaveBeenCalledWith(0); - }); - - describe('ProgressStep', () => { - it('should render with correct base className', () => { - expect( - list - .find(ProgressStep) - .at(0) - .children() - .hasClass(`${prefix}--progress-step`) - ).toEqual(true); - }); - - it('should render with a label', () => { - expect(list.find(ProgressStep).at(0).prop('label')).toEqual('label'); - }); - - it('should render with a description', () => { - expect(list.find(ProgressStep).at(0).prop('description')).toEqual( - 'Step 1: Getting Started with Node.js' - ); - }); - - it('should render description in <title> node', () => { - expect(list.find('ProgressStep title').at(0).text()).toEqual( - 'Step 1: Getting Started with Node.js' - ); - }); - - describe('current', () => { - it('should render a current ProgressStep with correct className', () => { - expect( - list - .find(ProgressStep) - .at(3) - .children() - .hasClass(`${prefix}--progress-step--current`) - ).toEqual(true); - }); - - it('should render a current ProgressStep with correct props', () => { - expect(list.find(ProgressStep).at(3).prop('current')).toBe(true); - }); - }); - - describe('complete', () => { - it('should render any completed ProgressSteps with correct className', () => { - expect( - list - .find(ProgressStep) - .at(0) - .children() - .hasClass(`${prefix}--progress-step--complete`) - ).toEqual(true); - }); - it('should render any completed ProgressSteps with correct props', () => { - expect(list.find(ProgressStep).at(0).prop('complete')).toBe(true); - }); - }); - - describe('incomplete', () => { - it('should render any incomplete ProgressSteps with correct className', () => { - expect( - list - .find(ProgressStep) - .at(5) - .children() - .hasClass(`${prefix}--progress-step--incomplete`) - ).toEqual(true); - }); - it('should render any incomplete ProgressSteps with correct props', () => { - expect(list.find(ProgressStep).at(5).prop('complete')).toBe(false); - }); - - it('should render any clickable ProgressSteps with correct classname', () => { - list.setProps({ onChange: jest.fn() }); - expect(list.find(`.${prefix}--progress-step-button`)).toHaveLength(6); // one button for each div - expect( - list.find(`.${prefix}--progress-step-button--unclickable`) - ).toHaveLength(1); // only the current step should be unclickable - }); - }); - }); - }); -}); diff --git a/packages/react/tasks/build-test-rtl.js b/packages/react/tasks/build-test-rtl.js index c7699438684e..ebb72c821cd0 100644 --- a/packages/react/tasks/build-test-rtl.js +++ b/packages/react/tasks/build-test-rtl.js @@ -1,5 +1,6 @@ 'use strict'; +const clipboard = require('clipboardy'); const prettier = require('prettier'); const CarbonComponents = require('@carbon/react'); const enquirer = require('enquirer'); @@ -215,6 +216,22 @@ async function main() { const testFile = writeTestFile(props, componentName, isSubComponent); + if (pathToComponent === '') { + const { copy } = await enquirer.prompt([ + { + type: 'confirm', + name: 'copy', + message: + 'Looks like no component path was found, do you want to copy the created tests?', + }, + ]); + + if (copy) { + clipboard.writeSync(testFile); + } + return; + } + await fs.writeFile(pathToComponent, testFile); console.log(`Test file created for ${componentName}! 🎉`); diff --git a/yarn.lock b/yarn.lock index 077a33be37b1..1c460f924eaa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2178,6 +2178,7 @@ __metadata: browserify-zlib: ^0.2.0 browserslist-config-carbon: ^11.0.0 classnames: 2.3.1 + clipboardy: ^2.1.0 copy-to-clipboard: ^3.3.1 css-loader: ^6.5.1 downshift: 5.2.1