Skip to content

Commit

Permalink
Merge pull request #3748 from terrestris/refactor-upload-button
Browse files Browse the repository at this point in the history
Refactor `UploadButton` to function component
  • Loading branch information
dnlkoch authored Feb 26, 2024
2 parents ce0b877 + 25159fa commit bd3b10b
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 58 deletions.
46 changes: 29 additions & 17 deletions src/Button/UploadButton/UploadButton.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,48 @@
import TestUtil from '../../Util/TestUtil';
import { fireEvent,render, screen } from '@testing-library/react';
import * as React from 'react';

import UploadButton from './UploadButton';

describe('<UploadButton />', () => {
it('is defined', () => {
expect(UploadButton).not.toBeUndefined();
expect(UploadButton).toBeDefined();
});

it('can be rendered', () => {
const wrapper = TestUtil.mountComponent(UploadButton);
expect(wrapper).not.toBeUndefined();
const { container } = render(<UploadButton />);
expect(container).toBeVisible();
});

it('renders an inputfield', () => {
const wrapper = TestUtil.mountComponent(UploadButton);
expect(wrapper.find('input').length).toBe(1);
});
it('applies inputProps to the input field', () => {
render(
<UploadButton
inputProps={{
role: 'test'
}}
/>
);

it('applies inputProps to the inputfield', () => {
const wrapper = TestUtil.mountComponent(UploadButton, {inputProps: {multiple: true}});
expect(wrapper.find('input[multiple=true]').length).toBe(1);
expect(screen.getByRole('test')).toBeInTheDocument();
});

it('renders a simplebutton if no children are given', () => {
const wrapper = TestUtil.mountComponent(UploadButton);
expect(wrapper.find('button').length).toBe(1);
it('renders a simple button if no children are given', () => {
render(<UploadButton />);
expect(screen.getByRole('button')).toBeInTheDocument();
});

it('calls a given click callback method onChange', () => {
const onChange = jest.fn();
const wrapper = TestUtil.mountComponent(UploadButton, {onChange});
wrapper.find('input').simulate('change');
render(
<UploadButton
onChange={onChange}
inputProps={{
role: 'test'
}}
/>
);

fireEvent.change(screen.getByRole('test'));

expect(onChange).toHaveBeenCalledTimes(1);
});

});
72 changes: 31 additions & 41 deletions src/Button/UploadButton/UploadButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as React from 'react';
import { CSS_PREFIX } from '../../constants';
import SimpleButton, { SimpleButtonProps } from '../SimpleButton/SimpleButton';

interface BaseProps {
export type OwnProps = {
/**
* The className which should be added.
*/
Expand All @@ -18,55 +18,45 @@ interface BaseProps {
* The onChange handler for the upload input field.
*/
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}
};

export type UploadButtonProps = BaseProps & SimpleButtonProps;
export type UploadButtonProps = OwnProps & SimpleButtonProps;

/**
* Class representing an upload button. Can be used as wrapper if children
* Component representing an upload button. Can be used as wrapper if children
* are given. Otherwise a Simplebutton will be rendered.
*
* To use a text with the UploadButton provide a SimpleButton as children.
*
* This automatically supports uploads via drag and drop from the operating
* system.
*
* @class The UploadButton
* @extends React.Component
*/
class UploadButton extends React.Component<UploadButtonProps> {

/**
* The className added to this component.
* @private
*/
_className = `${CSS_PREFIX}uploadbutton`;

/**
* The render function.
*/
render() {
const {
className,
children,
onChange,
inputProps,
...passThroughProps
} = this.props;

const finalClassName = className
? `${className} ${this._className}`
: this._className;

const button = <SimpleButton {...passThroughProps} />;

return (
<div className={finalClassName}>
{children || button}
<input type="file" onChange={onChange} {...inputProps} />
</div>
);
}
}
const UploadButton: React.FC<UploadButtonProps> = ({
className,
children,
onChange,
inputProps,
...passThroughProps
}) => {

const finalClassName = className
? `${className} ${CSS_PREFIX}uploadbutton`
: `${CSS_PREFIX}uploadbutton`;

const button = <SimpleButton {...passThroughProps} />;

return (
<div
className={finalClassName}
>
{children || button}
<input
type="file"
onChange={onChange}
{...inputProps}
/>
</div>
);
};

export default UploadButton;

0 comments on commit bd3b10b

Please sign in to comment.