Skip to content

Commit

Permalink
feat(radioComponent): updated according to PF-next demo (patternfly#756)
Browse files Browse the repository at this point in the history
Adds label option, more tests
  • Loading branch information
rvsia authored and tlabaj committed Oct 17, 2018
1 parent c381851 commit a62ee27
Show file tree
Hide file tree
Showing 10 changed files with 378 additions and 68 deletions.
12 changes: 8 additions & 4 deletions packages/patternfly-4/react-core/src/components/Radio/Radio.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { HTMLProps, FormEvent } from 'react';
import { HTMLProps, FormEvent, ReactNode } from 'react';
import { Omit } from '../../typeUtils';

export interface RadioProps
extends Omit<HTMLProps<HTMLInputElement>, 'type' | 'onChange' | 'disabled'> {
isDisabled: boolean;
isValid: boolean;
onChange(checked: boolean, event: FormEvent<HTMLInputElement>): void;
isDisabled?: boolean;
isValid?: boolean;
onChange?(checked: boolean, event: FormEvent<HTMLInputElement>): void;
id: string;
'aria-label': string;
label?: ReactNode;
name: string;
}

declare const Radio: React.SFC<RadioProps>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Checkbox } from '@patternfly/react-core';
import Controlled from './examples/ControlledRadio';
import Uncontrolled from './examples/UncontrolledRadio';
import Disabled from './examples/DisabledRadio';
import Custom from './examples/CustomLabelRadio';
import { Radio } from '@patternfly/react-core';

export default {
title: 'Radio',
components: {
Checkbox
Radio
},
examples: [Controlled, Uncontrolled, Disabled]
examples: [Controlled, Uncontrolled, Disabled, Custom]
};
42 changes: 29 additions & 13 deletions packages/patternfly-4/react-core/src/components/Radio/Radio.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
import React from 'react';
import styles from '@patternfly/patternfly-next/components/Check/check.css';
import { css } from '@patternfly/react-styles';
import PropTypes from 'prop-types';
import { css, getModifier } from '@patternfly/react-styles';

const propTypes = {
/** additional classes added to the Radio */
/** Additional classes added to the Radio. */
className: PropTypes.string,
/** Flag to show if the Radio selection is valid or invalid. */
isValid: PropTypes.bool,
/** Flag to show if the Radio is disabled. */
isDisabled: PropTypes.bool,
/** A callback for when the Radio selection changes. */
onChange: PropTypes.func
onChange: PropTypes.func,
/** Label text of the Radio. */
label: PropTypes.node,
/** Id of the Radio. */
id: PropTypes.string.isRequired,
/** Aria-label of the Radio. */
'aria-label': PropTypes.any.isRequired,
/** Name for group of Radios */
name: PropTypes.string.isRequired
};

const defaultProps = {
className: '',
isValid: true,
isDisabled: false,
onChange: () => undefined
onChange: () => undefined,
label: undefined
};

class Radio extends React.Component {
Expand All @@ -27,16 +36,23 @@ class Radio extends React.Component {
};

render() {
const { className, onChange, isValid, isDisabled, ...props } = this.props;
const { className, onChange, isValid, isDisabled, label, ...props } = this.props;
return (
<input
{...props}
className={css(styles.check, className)}
type="radio"
onChange={onChange ? this.handleChange : null}
aria-invalid={!isValid}
disabled={isDisabled}
/>
<div className={css(styles.check, className)}>
<input
{...props}
className={css(styles.checkInput)}
type="radio"
onChange={this.handleChange}
aria-invalid={!isValid}
disabled={isDisabled}
/>
{label && (
<label className={css(styles.checkLabel, getModifier(styles, isDisabled && 'disabled'))} htmlFor={props.id}>
{label}
</label>
)}
</div>
);
}
}
Expand Down
74 changes: 53 additions & 21 deletions packages/patternfly-4/react-core/src/components/Radio/Radio.test.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,65 @@
import React from 'react';
import { shallow } from 'enzyme';
import Radio from './Radio';
import { shallow } from 'enzyme';

const props = {
onChange: jest.fn(),
checked: false
};

test('controlled', () => {
const view = shallow(<Radio checked />);
expect(view).toMatchSnapshot();
});
describe('Radio check component', () => {
test('controlled', () => {
const view = shallow(<Radio checked id="check" aria-label="check" name="check" />);
expect(view).toMatchSnapshot();
});

test('uncontrolled', () => {
const view = shallow(<Radio />);
expect(view).toMatchSnapshot();
});
test('uncontrolled', () => {
const view = shallow(<Radio id="check" aria-label="check" name="check" />);
expect(view).toMatchSnapshot();
});

test('isDisabled', () => {
const view = shallow(<Radio isDisabled />);
expect(view).toMatchSnapshot();
});
test('isDisabled', () => {
const view = shallow(<Radio id="check" isDisabled aria-label="check" name="check" />);
expect(view).toMatchSnapshot();
});

test('label is string', () => {
const view = shallow(<Radio label="Label" id="check" checked aria-label="check" name="check" />);
expect(view).toMatchSnapshot();
});

test('label is function', () => {
const functionLabel = () => <h1>Header</h1>;
const view = shallow(<Radio label={functionLabel()} id="check" checked aria-label="check" name="check" />);
expect(view).toMatchSnapshot();
});

test('label is node', () => {
const view = shallow(<Radio label={<h1>Header</h1>} id="check" checked aria-label="check" name="check" />);
expect(view).toMatchSnapshot();
});

test('passing class', () => {
const view = shallow(
<Radio label="label" className="class-123" id="check" checked aria-label="check" name="check" />
);
expect(view).toMatchSnapshot();
});

test('passing HTML attribute', () => {
const view = shallow(
<Radio label="label" aria-labelledby="labelId" id="check" checked aria-label="check" name="check" />
);
expect(view).toMatchSnapshot();
});

test('radio passes value and event to onChange handler', () => {
const newValue = true;
const event = {
currentTarget: { checked: newValue }
};
const view = shallow(<Radio {...props} />);
view.find('input').simulate('change', event);
expect(props.onChange).toBeCalledWith(newValue, event);
test('Radio passes value and event to onChange handler', () => {
const newValue = true;
const event = {
currentTarget: { checked: newValue }
};
const view = shallow(<Radio id="check" {...props} aria-label="check" name="check" />);
view.find('input').simulate('change', event);
expect(props.onChange).toBeCalledWith(newValue, event);
});
});
Loading

0 comments on commit a62ee27

Please sign in to comment.