Skip to content

Commit

Permalink
Add: Introduce a useClickHandler hook to replace withClickHandler
Browse files Browse the repository at this point in the history
Add a new useClickHandler hook that implements the behavior of the
withClickHandler HOC. This allows to replace the HOC at the end.
  • Loading branch information
bjoernricks committed Mar 7, 2025
1 parent 00eefde commit a5951a3
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
89 changes: 89 additions & 0 deletions src/web/components/form/__tests__/useClickHandler.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/* SPDX-FileCopyrightText: 2025 Greenbone AG
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import {describe, test, expect, testing} from '@gsa/testing';
import useClickHandler from 'web/components/form/useClickHandler';
import {fireEvent, rendererWith, screen} from 'web/utils/Testing';

describe('useClickHandler tests', () => {
test('should call click handler with value', () => {
const {renderHook} = rendererWith();

const onClick = testing.fn();
const {result} = renderHook(() => useClickHandler({onClick, name: 'test'}));
result.current({target: {value: 'foo', name: 'test'}});

expect(onClick).toHaveBeenCalledWith('foo', 'test');
});

test('should call click handler with value from props', () => {
const {renderHook} = rendererWith();

const onClick = testing.fn();
const {result} = renderHook(() =>
useClickHandler({
onClick,
valueFunc: (event, props) => props.bar,
bar: 'baz',
}),
);
result.current({target: {value: 'foo', name: 'test'}});

expect(onClick).toHaveBeenCalledWith('baz', 'test');
});

test('should call click handler with name from props', () => {
const {renderHook} = rendererWith();

const onClick = testing.fn();
const {result} = renderHook(() =>
useClickHandler({
onClick,
nameFunc: (event, props) => props.name,
name: 'ipsum',
}),
);
result.current({target: {value: 'foo', name: 'test'}});

expect(onClick).toHaveBeenCalledWith('foo', 'ipsum');
});

test('should call click handler with converted value', () => {
const {renderHook} = rendererWith();

const onClick = testing.fn();
const {result} = renderHook(() =>
useClickHandler({
onClick,
convert: value => value.toUpperCase(),
}),
);
result.current({target: {value: 'foo', name: 'test'}});

expect(onClick).toHaveBeenCalledWith('FOO', 'test');
});

test('should work with a button component', () => {
const {render} = rendererWith();
const handleClick = testing.fn();
const ClickComponent = ({onClick}) => {
const handleClick = useClickHandler({onClick});
return (
<button
data-testid="button"
name="test"
value="foo"
onClick={handleClick}
/>
);
};
render(<ClickComponent onClick={handleClick} />);

const button = screen.getByTestId('button');
fireEvent.click(button);

expect(handleClick).toHaveBeenCalledWith('foo', 'test');
});
});
36 changes: 36 additions & 0 deletions src/web/components/form/useClickHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* SPDX-FileCopyrightText: 2025 Greenbone AG
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

const eventValue = (event, props) => event.target.value;
const eventName = (event, props) => event.target.name;
const noopConvert = value => value;

/**
* Custom hook to create a click handler function.
*
* @param {Object} params - The parameters for the click handler.
* @param {Function} [params.convert=noopConvert] - A function to convert the value before passing it to onClick.
* @param {Function} [params.valueFunc=eventValue] - A function to extract the value from the event and props.
* @param {Function} [params.nameFunc=eventName] - A function to extract the name from the event and props.
* @param {Function} params.onClick - The click handler function to be called.
* @param {...Object} params.props - Additional props to be passed to valueFunc, nameFunc and onClick.
* @returns {Function} - The click handler function.
*/
const useClickHandler = ({
convert = noopConvert,
valueFunc = eventValue,
nameFunc = eventName,
onClick,
...props
}) => {
const handleClick = event => {
if (onClick) {
onClick(convert(valueFunc(event, props), props), nameFunc(event, props));
}
};
return handleClick;
};

export default useClickHandler;

0 comments on commit a5951a3

Please sign in to comment.